Reducing Permission Warnings at Install

Shrink the install dialog of an MV3 extension: which permissions trigger warnings, replacing tabs with activeTab, narrowing hosts, moving features to optional permissions, and checking warnings before every release.

Published October 2, 2026 Updated October 2, 2026 7 min read
Table of Contents

The install dialog lists four lines: “Read and change all your data on all websites”, “Read your browsing history”, “Manage your downloads”, “Display notifications”. Half of the people who click “Add to Chrome” read that and click Cancel. Some of those warnings are necessary for the extension’s core feature; usually several are not — they come from a permission requested for convenience, a secondary feature, or a historical reason nobody remembers. Every warning removed raises install conversion and lowers review scrutiny, and permissions removed in an update never require users to re-accept anything. This guide finds and removes the unnecessary ones. It belongs to store submission and permissions compliance.

Which permissions produce warnings

Chrome shows warnings for permissions that grant access to sensitive data or capabilities, grouped into human-readable sentences. Host permissions produce the most prominent ones — “Read and change your data on example.com”, “…on a number of websites”, “…on all websites”. Among API permissions, tabs warns about browsing history (because it exposes URLs of all tabs), as do history, topSites and webNavigation; bookmarks, downloads, notifications, clipboardRead, nativeMessaging, geolocation, management, privacy and others have their own warnings. Many commonly used permissions produce none: storage, alarms, activeTab, scripting, contextMenus, sidePanel, offscreen, declarativeNetRequest without host permissions in some contexts. Optional permissions produce no install warning at all — only a prompt when requested.

Common permissions and their install warningsFrequently requested MV3 permissions, whether each produces an install warning in Chrome, and the usual lower-cost alternative.PermissionInstall warningAlternative<all_urls> hostsAll websitesactiveTab / narrow / optionaltabsBrowsing historyactiveTab, host accesswebNavigationBrowsing historytabs.onUpdated with hostsnotificationsDisplay notificationsOptional permissionstorage, alarms, scriptingNone—activeTab, contextMenusNone—
Several of the most common warnings have warning-free alternatives.

Step-by-step: trim the install dialog

1. See exactly what users see

1# Pack the build and drag the .crx into a clean Chrome profile to see the real dialog
2google-chrome --pack-extension=dist/chrome --pack-extension-key=dev-key.pem

Execution context: a terminal and a test Chrome profile. Unpacked extensions do not show the install dialog, so developers rarely see it. Packing locally and installing the .crx (with developer mode on) reproduces the dialog’s warnings exactly. Record them per release; any new line is a change worth questioning.

2. Map each warning to the code that needs it

1for p in tabs history bookmarks downloads notifications webNavigation; do
2  echo "== $p"; grep -rnoE "chrome\.$p\.[a-zA-Z]+" src | sort | uniq -c
3done

Execution context: a terminal over the source. A permission whose API is barely used — one chrome.tabs.query to read the current URL, one notification on a rare error — is a candidate for removal or an optional request. A permission whose API is not used at all is a leftover; remove it.

Reducing warnings step by stepList current warnings, map each to its code, replace tabs and broad hosts with activeTab where triggered by the user, narrow remaining hosts, move secondary features to optional permissions, and recheck the dialog.List warningspacked installMap to codegrep API usageactiveTabreplace tabs / hoststhenNarrow hostsnamed sitesOptional permissionssecondary featuresRecheck dialogevery release
Each step removes a warning or moves it to the moment it's needed.

3. Replace tabs and broad hosts with activeTab

1// Before
2{ "permissions": ["tabs", "scripting"], "host_permissions": ["<all_urls>"] }
3// After — user-triggered features only
4{ "permissions": ["activeTab", "scripting"] }

Execution context: the manifest. If the extension acts on the current page when the user clicks the toolbar button, a context menu item or a shortcut, activeTab grants exactly that tab’s URL and scripting access at that moment, with no install warning. This single change often removes the two most alarming warnings. See activeTab vs host permissions.

4. Move secondary features to optional permissions

1{
2  "permissions": ["activeTab", "scripting", "storage"],
3  "optional_permissions": ["notifications", "downloads", "bookmarks"],
4  "optional_host_permissions": ["https://*/*"]
5}
1// options.js — request when the user enables the feature
2exportToggle.addEventListener("change", async () => {
3  if (exportToggle.checked) exportToggle.checked = await chrome.permissions.request({ permissions: ["downloads"] });
4});

Execution context: the manifest and the options page. Features that some users never touch — exporting to a file, desktop notifications, bookmark import — should request their permissions when switched on, inside a click handler. The prompt then appears in context, to users who want the feature. See requesting optional permissions at runtime.

A permission moved from install to first useThe user installs with no notifications warning; later enables 'Notify me when sync fails' in options; the extension requests notifications from the click handler; the user approves in context.UserOptions pageChromeinstall — no notifications warningenable sync alertspermissions.request(notifications)prompt in contextAllow
The same permission, asked for at the moment it makes sense.

5. Narrow host permissions that must stay

1{ "host_permissions": ["https://api.readable.example/*", "https://*.docs.example.com/*"] }

Execution context: the manifest. When the extension genuinely needs persistent access to specific sites — its own API, a set of supported sites for automatic features — name them. The warning then names the sites rather than “all websites”, which users accept far more readily. See the review cost of all_urls and broad host patterns.

6. Plan permission additions in updates

Adding a warning-producing permission in an update disables the extension for every existing user until they accept the new warning in the extensions menu — many never do. Removing permissions never triggers this. When a new feature needs a new permission, ship it as an optional permission. If a required permission is unavoidable, bundle it into a release with a clear benefit and explain it in release notes.

7. Guard against regressions in CI

1// scripts/check-permissions.mjs
2const ALLOWED = new Set(["activeTab", "scripting", "storage", "alarms", "contextMenus", "sidePanel"]);
3const m = JSON.parse(await (await import("node:fs/promises")).readFile("dist/chrome/manifest.json", "utf8"));
4const extra = (m.permissions ?? []).filter((p) => !ALLOWED.has(p));
5if (extra.length || (m.host_permissions ?? []).some((h) => h === "<all_urls>")) {
6  console.error("Unreviewed install-time permissions:", extra, m.host_permissions); process.exit(1);
7}

Execution context: CI after the build. An allow-list of required permissions turns any new install-time permission into a failing build that someone must consciously approve, rather than a surprise in the next store review.

Common mistakes

  • tabs just to read the current URL. activeTab provides it on user action.
  • <all_urls> for click-triggered features. No warning needed with activeTab.
  • Secondary features as required permissions. Make them optional.
  • Adding required permissions in updates. Users get disabled extensions.
  • Never looking at the real dialog. Unpacked development hides it.

Explain the warnings that remain

Some warnings are unavoidable for an extension’s purpose — a password manager needs broad host access. For those, the listing should explain in plain words what the permission enables and what the extension does not do with it, ideally in the first lines of the description and in a screenshot of the options page that shows the user’s controls. Users who understand why a warning appears are far more likely to accept it than users who meet it cold in the install dialog.

Cross-browser variation

  • Chrome / Edge: warnings as described; optional permissions show no install warning.
  • Firefox: shows required permissions at install (including hosts from 127); optional permissions prompt on request; Firefox’s wording differs but the strategy is the same.
  • Safari: shows its own permission prompts per site on first use; reducing requested hosts still reduces prompts.

Verification

  1. Pack and install the previous and new builds; compare warning lines.
  2. Confirm each removed permission’s features still work (via activeTab or optional grants).
  3. Update a profile from the previous build and confirm the extension is not disabled for re-consent.
  4. Confirm the CI permission check fails when a test adds tabs.

FAQ

Does activeTab work with keyboard shortcuts?

Yes, commands declared in the manifest grant activeTab when invoked, like toolbar clicks and context menu items.

Is scripting a warning-producing permission?

No. It needs host access (from hosts or activeTab) to do anything, and that access is what warns.

Do optional permissions affect review?

Reviewers see them in the manifest and may ask about them, but they are generally viewed more favourably than required ones.

How do I know a warning-free alternative still works for everyone?

Test the user-triggered paths — toolbar click, context menu, keyboard command — on a profile without the removed permission, including on restricted pages where activeTab cannot help, so the UI explains rather than fails.

Other MV3 Architecture & Extension Lifecycle Resources