DEV Community

Cover image for 8 Shipped Chrome Extensions, 4 Ways to Declare Host Permissions
k-wada
k-wada

Posted on

8 Shipped Chrome Extensions, 4 Ways to Declare Host Permissions

I ship eight small Chrome extensions under Legacy Tools. They are all
Manifest V3, and they all need some form of access to the pages you
visit — that is what tools that check things before you send them do.

I have written before about the rules I give AI agents
so they never broaden permissions on their own. This post is about the
other side of that: the shapes the declarations themselves take.
Recently I put all eight manifests side by side (the versions shipped to
the Chrome Web Store as of 2026-08-22) and realized they ended up using
four different shapes to declare that access. None of this was planned
up front; each shape fell out of what the tool is. Here is the survey.

The four shapes

1. Everywhere, all the time — five extensions.
Safe Privacy Gate, Safe Attachment Check, Safe Mail Link Check, Site
Operator Check, Find My Age. These step in right before a send or a
click, and there is no way to know in advance which site that will
happen on. Interesting detail: only two of the five actually write
<all_urls> into host_permissions. The other three get the same
breadth from content_scripts.matches alone.

2. One fixed site — one extension.
Safe Night Check is a Gmail-only tool, so the whole declaration is a
single pattern: https://mail.google.com/*.

3. A fixed list plus optional grants — one extension.
Safe Privacy Mask enumerates thirty matches patterns for the AI chat
sites it supports, and puts <all_urls> into
optional_host_permissions so that any other site is granted only when
the user adds it, one prompt at a time.

4. activeTab only — one extension.
Copy & Prep ships no content script at all. It touches only the tab
where you just ran its context-menu action. Standing access: zero.

The part that surprised me

While checking what these declarations look like from the user's side
(on chrome://extensions, with the extensions side-loaded into
Chromium), two things stood out:

  • The Permissions section came up empty every time. I measured seven of the eight this way. Between them they use storage, scripting, contextMenus and activeTab — none of those produces a line in that box. "The permissions list is blank, so it must be harmless" is not a read you can make.
  • matches counts as a host permission. Safe Attachment Check declares no host_permissions at all, and its site-access wording was character-for-character identical to Safe Privacy Gate, which declares <all_urls> explicitly. You cannot shrink the warning by moving breadth out of host_permissions and into content_scripts.
  • Bonus: the list shown to users is deduplicated. Mask declares thirty patterns; the screen shows fifteen. A short list does not mean narrow coverage.

What I take from this

Permission declarations are not configuration. They are UI — shown to
the user, in their words, at install time and on the details page. The
shape you choose is a product decision: <all_urls> is honest for a
tool that must work everywhere, a fixed list is honest for a
single-site tool, and activeTab is worth the extra design work when
"only when I ask" is the actual contract.

I wrote up the longer versions of both halves of this:

Top comments (0)