The build story behind Extension Permission Monitor: reading installed extensions with chrome.management, translating permissions, designing risk cues, and shipping a calmer privacy tool.

I did not start Extension Permission Monitor because I wanted to build a security product.
I started it because my own browser felt messy.
I had too many Chrome extensions installed, and the uncomfortable part was not the number. It was the uncertainty. I could recognize some of the icons, but I could not explain what half of those extensions were allowed to do.
That is a strange feeling when your browser is where you work, log in, write, test products, check dashboards, and manage money.
So the first version of Extension Permission Monitor came from a very plain question:
Can I make Chrome extension permissions understandable without making the user feel stupid or scared?
The extension is now live on the Chrome Web Store:
Install Extension Permission Monitor
This is the story of how I built it, what I got wrong first, and why the hardest part was not the API.
The technical foundation is Chrome's management API.
That API lets an extension query information about installed extensions and apps. For my use case, the important method is chrome.management.getAll().
The first useful experiment looked something like this:
const installedItems = await chrome.management.getAll()
const extensions = installedItems.filter((item) => {
return item.type === 'extension'
})
console.log(extensions.map((extension) => ({
id: extension.id,
name: extension.name,
enabled: extension.enabled,
permissions: extension.permissions,
hostPermissions: extension.hostPermissions,
})))That tiny script changed the project from an idea into a product.
Seeing my extensions as structured data made the problem obvious. Chrome already knew what was installed. It already knew which permissions were declared. The missing layer was explanation.
The raw data was there.
The human meaning was not.
My first UI was too developer-focused.
It listed every permission like this:
storage
tabs
scripting
management
contextMenus
<all_urls>That was technically honest, but not very helpful.
A developer might understand those names. A normal user sees a pile of browser vocabulary and has to guess what matters.
Even worse, raw permission names can mislead in both directions.
Some permissions sound scary but are reasonable in context. Some sound boring but become important when combined with broad site access. Some only make sense when you know how Chrome extension architecture works.
So I changed the goal.
The UI should not merely display permissions.
It should interpret them.
I started writing plain-English explanations for common permissions.
Something like:
const permissionExplanations: Record<string, string> = {
storage: 'Can save its own settings and local extension data.',
tabs: 'Can access information about browser tabs, such as titles and URLs.',
scripting: 'Can inject code into pages where it has access.',
history: 'Can read your browsing history.',
cookies: 'Can access cookies for sites where it has permission.',
management: 'Can read information about installed extensions and apps.',
}This looked simple, but it forced a product decision.
Should the copy be short or precise?
Short copy is easier to scan. Precise copy is safer. But if the explanation becomes too technical, the product fails the original mission.
I landed on a rule:
The first sentence should be understandable by a non-developer. The details can come after.
That rule shaped the whole interface.
At first, I wanted to label extensions as safe or risky.
That was tempting because it makes for a clean UI.
Green is safe. Red is dangerous. Done.
But the more I worked with real extensions, the less honest that felt.
A password manager can have powerful permissions for a good reason. A grammar tool may need broad access because it checks text across many websites. An ad blocker may need wide access to filter requests. A developer tool may need to inspect pages deeply.
The permission list tells me capability.
It does not prove intent.
That distinction changed the product language.
Instead of saying:
This extension is dangerous.I wanted to say:
This extension has broad access. Keep it only if you trust it and still use it.That is less dramatic, but more truthful.
Extension Permission Monitor is not trying to accuse extensions. It is trying to make access visible.
I still wanted a quick way to sort attention.
If someone has twenty extensions installed, they need a starting point. They should not have to inspect every item with equal effort.
So I built a simple risk scoring layer.
The score considers things like:
A simplified version looks like this:
function scoreExtension(input: ExtensionInput) {
let score = 0
for (const permission of input.permissions) {
score += scorePermission(permission)
}
if (hasBroadHostAccess(input.hostPermissions)) {
score += 30
}
if (
input.permissions.includes('scripting') &&
hasBroadHostAccess(input.hostPermissions)
) {
score += 20
}
return Math.min(score, 100)
}But I learned quickly that a score without explanation feels arbitrary.
So every risk cue needed a reason.
Not just:
Risk: 72But:
This extension can run on many websites and inject code where it has access.That is the real value.
Numbers help users prioritize. Explanations help them decide.
API permissions are already tricky, but host permissions add another layer.
An extension might have access to one domain:
https://example.com/*Or broad access:
<all_urls>The same API permission can mean different things depending on where it applies.
scripting on one website is not the same as scripting across every website. A content script that only runs on one SaaS dashboard is not the same as one that can match every page the user visits.
So the scoring and explanation had to treat host access as first-class data, not a footnote.
The plain-English version became:
Where can this extension operate?That question made the UI easier to reason about.
First show what the extension can do.
Then show where it can do it.
That is the mental model normal users need.
chrome.management.getAll() can return more than the extensions a user thinks about.
There may be apps, themes, and the monitor extension itself.
So I filtered aggressively:
function shouldShowExtension(item: chrome.management.ExtensionInfo) {
if (item.type !== 'extension') return false
if (item.id === chrome.runtime.id) return false
return true
}That small detail matters.
If the dashboard includes irrelevant items, users stop trusting it. A privacy tool should feel quiet and careful. It should not dump raw platform data and make the user clean it up.
Good security UX is often about removing noise.
This surprised me.
I thought the hard part would be reading installed extensions, designing the UI, and building the scoring model.
Those were real tasks, but the permission copy took more emotional energy.
Every explanation had to avoid two traps.
Trap one: make the permission sound harmless when it is actually meaningful.
Trap two: make the permission sound terrifying when it is commonly used for legitimate features.
That is a narrow path.
For example, a lazy explanation for tabs might say:
Can access your tabs.That is not wrong, but it is not enough.
A better explanation is closer to:
Can access information about browser tabs, such as titles and URLs. This is commonly used by extensions that organize tabs or respond to the current page.It gives the user a capability and a normal use case.
That is the tone I wanted throughout the product.
Calm, honest, useful.
The dashboard has one job:
Help the user decide what deserves attention.
So I avoided making it feel like an enterprise security console.
A normal user does not need ten charts. They need a readable list.
The useful card or row includes:
I kept asking myself:
If someone opens this for five minutes, what should they do next?
That question pushed the UI toward practical decisions:
The product is better when the next action is obvious.
This is important.
Extension Permission Monitor cannot know whether an extension developer is trustworthy.
It cannot know whether a permission is being abused.
It cannot inspect every line of extension code and produce a moral verdict.
What it can do is show declared capability clearly.
That is still valuable.
A lot of privacy work starts with visibility.
If you can see what is installed, what access it has, and whether you still use it, you can make better decisions.
That is the product boundary I am comfortable with.
I would rather underclaim and be trusted than overclaim and make the tool feel fake.
Publishing the extension made the permission copy even more important.
The product itself needs the management permission. That sounds sensitive, especially for a tool about privacy.
So the listing had to explain why:
The management permission is used to read the list of your installed extensions, their permissions, and their enabled status. Extension Permission Monitor does not install, uninstall, enable, or disable extensions. It only reads and explains information about extensions already installed in your browser.That explanation is not marketing copy. It is trust copy.
And trust copy should be specific.
If an extension asks for a permission, the user deserves a direct explanation of what the extension does with it and what it does not do with it.
If I were starting again, I would write the permission explanation system even earlier.
I spent too much time on the dashboard before fully solving the language problem.
Now I would start with a table like this:
type PermissionExplanation = {
permission: string
plainMeaning: string
commonUseCases: string[]
whyItMatters: string
attentionLevel: 'low' | 'medium' | 'high'
}Then I would build the UI around that structured explanation.
The product is not the table. But the table forces clarity.
It makes every explanation consistent and easier to test.
Shipping the extension made the project feel real in a different way.
A local tool can be rough. A public extension has to earn trust from the first screen.
Users are right to be cautious with browser extensions. They live close to sensitive work. They can become invisible over time. They can ask for broad access. They can be useful and still deserve scrutiny.
That is why this project matters to me.
Not because I think everyone should uninstall half their extensions.
Because I think people should understand what they have installed.
A browser should not become a drawer of forgotten permissions.
The technical foundation of Extension Permission Monitor is simple enough to describe:
Use Chrome's management API, read installed extensions, inspect permissions, explain them, and help the user prioritize review.
But the real product is not the API.
The real product is translation.
From developer language to user language.
From raw permission names to practical meaning.
From vague anxiety to informed decisions.
That is the part I care about most.
And that is why I built it.
Productivity-focused Chrome extensions built for developers and power users.

How I Check Whether a Chrome Extension Is Asking for Too Much Access I used to install Chrome extensions the way most people install them: I saw a useful feature, checked a few reviews, clicked install, and moved on. That sounds normal because it is normal. Extensions are supposed to feel lightweight. A screenshot...

The hardest part of Chrome extension permissions is not that the words are technical. The hardest part is that the words do not map cleanly to what normal people are trying to understand. A user does not really care whether a permission is called , , , , or . They care about something simpler: What can this extension...

Most people do not need a complicated browser security routine. They need a small habit they will actually repeat. That is how I think about auditing Chrome extensions now. Not as a dramatic security cleanup. Not as a paranoid weekend project. Just five minutes every now and then to ask a simple question: What...