Most of us are laser-focused on patching Windows and keeping our apps up to date. But what about browser extensions? Do we assume they’re safe just because they come from the Chrome Web Store or Edge Add-ons site?
In reality, extension stores are full of apps. Thats the best way to think about extensions. All purport to be helpful, some are questionable, and some are downright risky. Since these mini-apps run inside your browser with sometimes powerful permissions, they can do everything from blocking ads and translating languages…to silently capturing your data.
What are Browser Extensions?
Think of browser extensions as mini applications that run inside the browser, often with surprisingly powerful permissions. They can do genuinely useful things like block ads, manage passwords, or translate languages…or they can quietly steal your data.
And if you’ve ever fallen into a Wikipedia rabbit hole, you’ll know how quickly that world can get overwhelming. As of 2024, there were over 138,000 extensions available in the Google Chrome Web Store alone. That’s a lot of potential “helpers” and a lot of potential “risks”.

Anatomy of an Extension
Extensions might look simple at first glance, just a one-click install from a browser store. Under the hood, though, they are made up of a collection of files that live in the user’s profile like a fungus swarm that hides in the sole of your trainers (sneakers for US audience).
Inside those profile directories you will find scripts, images, and manifest files. Together, these define the behaviour of the extension. The manifest acts as the blueprint, describing what the extension does, which permissions it needs, and where its resources are located.
You will also find JavaScript files that provide the core logic of the extension. These scripts can run in the background, inject code into active web pages, or interact directly with host(browser) APIs (more on those later). Alongside the code, there are usually images and icons that make up the interface elements the user sees in the toolbar or within the extension’s menus
Here is an example of the Graph X-Ray extension for Microsoft Edge, showing the folder structure in the user profile. Notice the presence of JavaScript bundles and other static resources like the logo.

Because these components are stored per profile, multipl users on the same machine can have completely different sets of extensions, and even one user can maintain separate extension lists across multiple browser profiles. This decentralised design makes extensions flexible and personal, but it also complicates auditing and security. There is no single “extensions folder” to review at the system level. This makes extension discovery much more complex than normal “apps” where we can often guarentee the presence of “soemthing” in the registry’s uninstall hive that the IME can scrape and send back to Intune.
Each browser profile keeps a record of its installed extensions in a central file. For Chromium-based browsers like Chrome and Edge, this is the Preferences
file, a JSON document that lists the extensions for that profile, their state (enabled or disabled), and the permissions and host access they request. In Firefox, the equivalent is the extensions.json
file, which performs the same role, it maps each extension’s ID to its metadata, version, and permissions. These files are the first place you should look if you want to know what extensions are present and what evil powers they have.

The actual code and resources for each extension live in the profile’s Extensions
folder. In Edge, CHrome and other Chromium browsers, the contents are unpacked so you can directly browse JavaScript bundles, manifests, images, and other static assets. This means the logic and resources of the extension are sitting on disk in plain sight. In Firefox, by contrast, the Extensions
folder contains .xpi
packages. These are signed ZIP archives that bundle the manifest, scripts, and resources together. They are compressed and less immediately readable, but they serve the same purpose – loading the extension into the browser with its declared permissions.

How we got this far into the blog without PowerShell I do not know – forgive me. Here is a real simple way to find extensions in the logged on users Edge profile(s).
$base = "$env:LOCALAPPDATA\Microsoft\Edge\User Data" Get-ChildItem $base -Directory | ForEach-Object { $p = $_; $pref = "$($p.FullName)\Preferences" if (Test-Path -Path $pref) { ($j = Get-Content $pref -Raw | ConvertFrom-Json).extensions.settings.PSObject.Properties | Where-Object { -not $_.Value.state -or $_.Value.state -eq 1 } | ForEach-Object { if ($_.Value.manifest) { $m = $_.Value.manifest [PSCustomObject]@{ Profile = $p.Name Path = $p.FullName ExtensionID = $_.Name Name = if ($m.browser_action.default_title) { $m.browser_action.default_title } else { $m.name } Version = $m.version } } } } } | Format-Table -AutoSize

Diving Deeper – Permissions that Manifest Themselves
Did I just throw a 404 at you? – “No Care Found“. Why should you give a monkey’s? Let’s look at why the permissions extensions that are granted – matter.
The truth is extensions can be a backdoor that’s often overlooked. Attackers know this. In fact, as reported by Darktrace in 2024 (interesting read), the credentials of an employee at a data security company were compromised. With that access, the attackers pushed a malicious update to the company’s Chrome extension. Because browser extensions auto-update silently in the background, the malware spread into customer environments without a single click from the end user.
The timing was carefully chosen too. It happened over the Christmas period when many businesses had fewer staff watching alerts. By the time people noticed, the extension had already been weaponised to establish a foothold in corporate networks.
And this wasn’t an isolated case. Reports in early 2025 revealed 33 Chrome extensions that had gone rogue, either compromised or malicious by design.
So why should you care? Because these aren’t obscure one-off tools. They’re widely installed add-ons that users trust. And once an extension has the wrong permissions, it can read your clipboard, intercept your web traffic, or inject code into every page you visit.
Trust by Popularity Sucks
Trusting an extension just because it’s popular is a false sense of security. In fact, the more users an extension has, the more attractive it becomes as a target for malicious actors.
Factoid incoming Lois Lane…popular extensions often get bought and sold. Sometimes to legitimate companies looking for ad reach, but sometimes to actors who want access to the user base itself. Once in new hands, the extension can be updated to collect data, push ads, or worse, act as a delivery mechanism for malware.
And if a popular extension is compromised, it may suddenly request additional permissions through an update. What started as a simple utility, maybe a coupon finder or a screenshot tool, could suddenly ask to read your browsing history, access your clipboard, or inject scripts into every site you visit.
Fun Fact…Popularity does not equal safety.

I am not suggesting that the extension shown above is unsafe. I am simply using it as an example to illustrate how popularity can turn any extension into a high-value target. In some cases, widespread adoption can actually make an extension more dangerous because it becomes a more attractive prize for malicious actors to compromise or acquire.
API Permissions
API permissions describe what the extension is capable of doing. These include things like reading and writing to the clipboard, monitoring network requests, or injecting code into pages. In Chromium browsers like Edge, you’ll find these inside the Preferences
file under the extension’s manifest
entry.
Here’s a real-world snippet from a Preferences
file for Edge looking at the Graph X-Ray Extension.
"abcdefghijklmnop": { "manifest": { "name": "Graph X-Ray", "permissions": [ "storage", "tabs", "webRequest", "clipboardRead", "clipboardWrite" ], "host_permissions": [ "https://graph.microsoft.com/*", "https://*/*" ] } }
In this case, the Graph X-Ray extension is asking to use APIs like webRequest
(monitoring network traffic) and clipboard access, both of which could be considered sensitive.
Host Permissions
Host permissions describe where those capabilities can be used. An extension might have the scripting
API available, but the host permissions decide whether it can inject scripts on github.com
, microsoft.com
, or on all sites (https://*/*
).
In Firefox, the extensions.json
file exposes this clearly. Here’s an example entry from the Bitwarden Password Manager.
"userPermissions": { "permissions": [ "alarms", "clipboardRead", "clipboardWrite", "contextMenus", "tabs", "webNavigation", "webRequest", "webRequestBlocking" ], "origins": [ "<all_urls>", "*://*/*", "file:///*" ] }
This tells us the Bitwarden extension is allowed to interact with all URLs (<all_urls>
), as well as use powerful APIs like webRequestBlocking
. For a password manager, this makes sense, but for a random “free coupon finder” extension this should be a red flag.
Why API and Host Permission Matter
By combining API permissions (what it can do) with host permissions (where it can do it), you get the true picture of an extension’s power. This is why extension manifests are critical for auditing, and also why a simple “click > install” can open a huge security backdoor.
At this point you might be asking, “Okay, but how do I know which permissions are bad and which are acceptable?“
Here’s the fun part…(mini drum roll)…there isn’t a single universal standard or magic reference table we can all agree on. So how can you begin to think about categorizing the extension permissions into a common “critical, high, medium, low” bucket?
I would argue, that critical permissions are those that give an extension the ability to intercept traffic, execute arbitrary code, or capture sensitive data across all sites. High-risk permissions give extensions might give visibility into user activity like history, downloads, or clipboard access. Medium and low permissions might typically involve browser UI or local features that, while not harmless, don’t pose the same systemic risk.
The point isn’t to memorise every single permission. It’s to recognise that some permissions might be red flags the moment you see them. Let’s take Bitwarden Password manager as an example (Ill share some cool code later on how I classifgied this).

Host Permissions
Where can the extension access:-
- https://*/* = ALL HTTPS websites
- http://*/* = ALL HTTP websites
- file:///* = Local Files
API Permissions
What are the capabilities of the extension:-
- webRequest = Monitor all network traffic
- scripting = Inject code into pages
- clipboardRead/Write = Access clipboard data
- tabs = Access to tab URLs, titles, content
webRequest + https://*/* Extension can intercept all HTTPS traffic (think banking, email, work)
scripting + https://*/* = Extension can inject code into every website (Think keyloggers, fake forms)
Classification of Permissions
Now here’s the nuance. A permission might be classified as critical, but that doesn’t mean the extension is automatically malicious. It might simply need that level of access to do the thing its makers intended it to do. Password managers, like Bitwarden, often require powerful permissions to function properly.
This is why it’s important for each organisation to build its own classification model. Decide what risks you are willing to accept, which permissions are fine under certain business contexts, and which should be flagged to admins for review. From there, you can enforce those decisions, blocking extensions that exceed your risk tolerance while allowing approved ones through.
The goal isn’t to ban every extension that looks scary. It’s to create an “acceptable use” model. What’s okay, what’s explicitly allowed, and what should be blocked or at least investigated before it spreads through your environment.
What does acceptable look like in your org?
This is not ME saying YOU should adopt this approach pictured below. But here is an example of how you might classify API permissions.

What about host permissions, they should be classfied too right? Yes. Although trickier, there might be some locations the extension is trying to access that you might outright think – nah…thats too risky.

Most, good, threat and vulnerability management solutions have their own way of classifying browser extension risk. Microsoft Defender Vulnerability Management, for example, includes extension visibility and will highlight extensions with risky or excessive permissions. Other enterprise security tools use similar scoring systems to help you quickly see which extensions pose the greatest potential impact.

https://learn.microsoft.com/en-us/defender-vulnerability-management/tvm-browser-extensions
That said, you should take time to understand their classification methodolgy. I would still suggest that their scoring should be treated as a guide, not a final verdict.
The important thing to remember is that these classifications in this section are guidance, not gospel. They could provide a baseline, but your organisation still needs to define its own thresholds. What one company considers acceptable may be completely out of bounds for another, depending on the sensitivity of data and/or regulatory requirements.
One final thing to consider when trying to understand how to classify permissions is that some extension permissions will trigger a prompt, such as access to the camera, microphone, location, clipboard, or USB devices. In these cases, the browser asks the user before granting access, with the default behaviour set to “Ask.” That being said, many of the most powerful permissions, like webRequest, scripting, cookies, tabs, or history, are typically granted at install time. Once the extension is approved, those capabilities are enabled without any further confirmation, which is why they might pose the highest risk.
PowerShell your way to success
I put together a PowerShell script that enumerates browser extensions for Edge, Chrome, and Firefox across all user profiles on a machine. It parses the Preferences
or extensions.json
files, pulls out metadata such as the extension ID, name, version, and declared permissions, then assigns a risk level based on commonly used API and host permission categories. I defined the risk categories, you should review them and not use my discernment for your security posture.

The script ships with predefined classification arrays for API permissions ($apiRiskCategories
) and host permissions ($hostRiskCategories
). These mappings are based on my own risk perception around what’s “Critical”, “High”, “Medium”, or “Low.” However, every organisation will have its own risk appetite. Adding or removing entries from the arrays instantly adjusts how the script classifies extensions.

$apiRiskCategories = @{ "Critical" = @("webRequest", "webRequestBlocking", "webRequestAuthProvider", "cookies", "nativeMessaging", "debugger", "scripting", "tabCapture", "management", "clipboardRead", "geolocation", "camera", "microphone", "desktopCapture") "High" = @("history", "downloads", "devtools", "clipboardWrite", "contentSettings", "proxy", "webNavigation", "privacy", "tabs", "identity", "pageCapture") "Medium" = @("bookmarks", "topSites", "storage", "notifications", "contextMenus", "offscreen", "activeTab", "webview") "Low" = @("alarms", "background", "idle", "fontSettings", "printing", "favicon", "unlimitedStorage", "system.cpu", "system.memory", "system.network", "ttsEngine", "telemetry", "mozillaAddons", "systemPrivate") } $hostRiskCategories = @{ "Critical" = @("<all_urls>", "*://*/*", "file:///*", "*://*/", "https://*/*", "http://*/*", "*://*/*/*", "ftp://*/*") "High" = @("*://github.com/*", "*://gmail.com/*", "*://outlook.com/*", "*://docs.google.com/*", "*://drive.google.com/*", "*://*.google.com/*", "*://microsoft.com/*", "*://*.microsoft.com/*", "*://office.com/*", "*://*.office.com/*", "*://sharepoint.com/*", "*://*.sharepoint.com/*", "*://onedrive.com/*", "*://*.onedrive.com/*", "*://azure.com/*", "*://*.azure.com/*", "*://aws.amazon.com/*", "*://*.aws.amazon.com/*", "*://console.cloud.google.com/*", "*://banking.com/*", "*://*.bank/*", "*://paypal.com/*", "*://stripe.com/*", "*://slack.com/*", "*://teams.microsoft.com/*", "*://zoom.us/*") }
Because the script is modular, you could also adapt it for proactive remediation in Intune. Instead of just outputting results locally, you could modify the script to log discoveries into a central store such as Log Analytics. That way, every time a device checks in, its installed extensions and associated risk levels are uploaded to your workspace. From there you can build dashboards, alerts, or even automation that flags newly discovered risky extensions for review. Heck – Mi might even blog on that if the sun cycles allow for it one day.
In short, the script gives you a practical starting point. Audit what’s installed, align permissions with your own classification model, and if needed, extend it to become part of your continuous monitoring pipeline.
https://github.com/byteben/MEM/blob/main/Intune/Get-BrowserExtensions.ps1
Intune Policy – Taking Back Control
If Intune gives you the ability to create a policy to manage browser extensions, you should be doing it. Even if you think your organisation only uses Microsoft Edge, or even if inventory reports suggest Chrome and Firefox aren’t present, don’t assume that’s the whole story. Users can install browsers directly into their own profiles without admin rights. Unless you’ve fully locked that down with the likes of WDAC (Hats off to you if you did this and users can still use their computer), you should assume unmanaged browsers can and will appear.
Simply put…if you only deploy Edge extension policies because you believe “everyone uses Edge,” you are already a step behind. Users may be running Chrome, Firefox, Brave or more from their profile, and without policy you have no control over what extensions get installed.
In the following section, we’ll walk through how to use Intune policy to block all extensions by default and then whitelist only the ones you’ve evaluated, risk-assessed, and formally approved.
This “deny-by-default” model may sound strict, but it’s the most effective way to protect users from malicious or compromised extensions while still allowing the trusted tools they need to stay productive.
Quick Tip
When blocking extensions with policy, you will need to know the extension id. The same extension id is not used intercahngeably between all Chromium based browsers. Below you can see the same Graph X-Ray extension for Edge and Chrome are using a differnet id. Nice that – Industry standardization at its finest again.

Microsoft Edge
Microsoft Edge is the easiest browser to control through Intune because all the necessary settings are available directly in the Settings Catalog. With a single profile, you can enforce 3 key rules:
- Block sideloaded extensions
Prevent users from installing extensions by dropping files into the registry or injecting JSON configuration. This closes off the “back door” method of sneaking in unmanaged extensions. - Block all extensions by default
Use a wildcard (*) to block every extension. This is your deny-by-default baseline and ensures nothing unexpected can be installed. - Whitelist only approved extensions
Once you’ve evaluated and risk-assessed extensions, you can explicitly allow them by adding their IDs to the exemption list. In the example shown, password managers like 1Password, Bitwarden, and Keeper are permitted, while everything else remains blocked.

Once deployed, you can verify the policy is in effect by navigating to edge://policy

In the example below, I already had Graph X-Ray extension installed but when my policy hit the device, it blocked it.

Google Chrome
Google Chrome is as equally easy to control now, through Intune, as Edge, because the ADMX templates are available directly in the Settings Catalog. With a single profile, you can enforce the same 3 key rules:
- Block sideloaded extensions
Prevent users from installing extensions by dropping files into the registry or injecting JSON configuration. This closes off the “back door” method of sneaking in unmanaged extensions. - Block all extensions by default
Use a wildcard (*) to block every extension. This is your deny-by-default baseline and ensures nothing unexpected can be installed. - Whitelist only approved extensions
Once you’ve evaluated and risk-assessed extensions, you can explicitly allow them by adding their IDs to the exemption list. In the example shown,Graph X-Ray is permitted, while everything else remains blocked.

Now if you try to install an extension not in the allow list, you will be promptly told to go away.

Mozilla Firefox
Unlike Edge and Chrome, Firefox doesn’t have native settings in the Intune catalog. Instead, you need to bring your own ADMX templates and configure the policy using JSON. It’s a little more work, but once set up, you get the same level of control.
1. Import the Firefox ADMX templates into Intune
- Download the official Mozilla ADMX files for Firefox from https://support.mozilla.org/en-US/kb/managing-firefox-intune
- In Intune, go to Devices > Configuration profiles > Import ADMX and upload the templates.
Tip: Import the the Mozilla template BEFORE the Firefox template to avoid a dependency issue

- Once imported, you’ll see them listed under “Imported Administrative Templates (Preview).”

2. Create a new profile and define your extension management JSON
- In Intune, create a new profile using Templates > Imported Administrative Templates (Preview).
- Navigate to the Firefox Extension Management setting.
- Add a JSON policy that blocks everything by default (
"*" : { "installation_mode": "blocked" }
) and whitelists only the extensions you approve by their IDs and update URLs.
Example:
{ "*": { "installation_mode": "blocked", "blocked_install_message": "Only 1Password and Bitwarden extensions are allowed." }, "{d634138d-c276-4fc8-924b-40a0ea21d284}": { "installation_mode": "allowed", "install_url": "https://addons.mozilla.org/firefox/downloads/latest/1password-x-password-manager/latest.xpi" }, "{446900e4-71c2-419f-a6a7-df9c091e268b}": { "installation_mode": "allowed", "install_url": "https://addons.mozilla.org/firefox/downloads/latest/bitwarden-password-manager/latest.xpi" } }
Tip: You can build the slug for the JSON by observing the SourceURL in the extensions.json

Compress the JSON to a single line and add it to the Extrension Management (JSON on one line) policy item.

The final JSON might look like this:
{"*":{"installation_mode":"blocked","blocked_install_message":"Only 1Password and Bitwarden extensions are allowed."},"{d634138d-c276-4fc8-924b-40a0ea21d284}":{"installation_mode":"allowed","install_url":"https://addons.mozilla.org/firefox/downloads/latest/1password-x-password-manager/latest.xpi"},"{446900e4-71c2-419f-a6a7-df9c091e268b}":{"installation_mode":"allowed","install_url":"https://addons.mozilla.org/firefox/downloads/latest/bitwarden-password-manager/latest.xpi"}}
Once deployed, you wont be able to add any extension not marked as “allowed” in your JSON.

Summary
Browser extensions aren’t just harmless little add-ons. They’re mini-apps with surprising levels of power, and if left unchecked, they can become one of the sneakiest backdoors into your org.
We’ve covered a lot here, from dissecting manifests and permissions, to running PowerShell audits, to finally putting some guardrails in place with Intune policies for Edge, Chrome, and Firefox.
The bottom line for me is deny by default, allow only what you trust. Your future self (and your security team) will thank you but your users might grumble. There is always a trade off between being secure and being productive.
My big thing for you to takeway is just because an extension has five stars and ten million downloads, it doesn’t mean it’s safe. It might just mean it’s a juicier prize for malicious actors to try to compromise. Popularity contests are great for TV talent shows, not so much for enterprise security.
Add comment