Enforce browser policies and extension allowlists on managed endpoints
For developers and endpoint admins managing Chrome, Edge, and Firefox on company devices. This shows the exact policy files, registry keys, and verification commands to lock down risky browser features and control which extensions can run without guessing through vendor-specific consoles.
TL;DR — The fastest path is to deploy OS-level browser policies, not per-user settings: set extension installation to block by default, allowlist only approved IDs, force-install required security extensions, and disable developer-risk features like unsigned extensions and password-manager sync where your policy requires it. If policies appear ignored, the most likely fix is putting them in the wrong scope or path: Chrome/Edge need machine policy locations, and Firefox needs
distribution/policies.json. Reading time: ~5 min
Goal
When you finish, managed endpoints will enforce browser hardening at startup: only approved extensions can run, required extensions install automatically, and the browser reports the active policies in its built-in policy page so you can prove the fleet is actually locked down.
Prerequisites
- Local admin or endpoint-management rights on the target OS
- Access to your fleet management tool or a way to deploy files/registry settings remotely
- One test device for each browser/OS combination you support
- Browser versions currently in fleet: Chrome/Chromium, Edge, and/or Firefox — check with:
google-chrome --version 2>/dev/null || chromium --version 2>/dev/null || echo "Chrome/Chromium not installed"
microsoft-edge --version 2>/dev/null || echo "Edge not installed"
firefox --version 2>/dev/null || echo "Firefox not installed"
- Extension IDs for anything you will allow or force-install
- On Windows, PowerShell 5.1+ or PowerShell 7+
- On Linux, root access and
jqoptional for JSON validation:
jq --version || echo "jq not installed"
Steps
Step 1: Collect the exact extension IDs and update URLs
For Chrome/Edge extensions, get the ID from the store URL or from the browser’s extensions page. For Firefox, get the add-on ID from the add-on manifest or enterprise docs.
# Example IDs used below; replace with your real ones
export UBO_CHROME_ID="cjpalhdlnbpafiamejdnhcphjbkeiagm"
export OKTA_CHROME_ID="glnpjglilkicbckjpbgcfkogebgllemb"
export EDGE_STORE_UPDATE_URL="https://edge.microsoft.com/extensionwebstorebase/v1/crx"
export CHROME_STORE_UPDATE_URL="https://clients2.google.com/service/update2/crx"
Success looks like: you have a list of exact IDs and one update URL per browser family.
Step 2: Apply Chrome policy to block all extensions except approved ones
On Windows, write machine policy under HKLM. On Linux, write JSON under /etc/opt/chrome/policies/managed/ for Google Chrome or /etc/chromium/policies/managed/ for Chromium.
⚠️ Blocking all extensions can immediately disable developer tools add-ons, password managers, and accessibility tools. Put required business extensions in the allowlist or force-install list before broad rollout.
Windows (Chrome):
reg add "HKLM\SOFTWARE\Policies\Google\Chrome" /v BrowserSignin /t REG_DWORD /d 0 /f
reg add "HKLM\SOFTWARE\Policies\Google\Chrome" /v SyncDisabled /t REG_DWORD /d 1 /f
reg add "HKLM\SOFTWARE\Policies\Google\Chrome" /v PasswordManagerEnabled /t REG_DWORD /d 0 /f
reg add "HKLM\SOFTWARE\Policies\Google\Chrome" /v ExtensionManifestV2Availability /t REG_DWORD /d 2 /f
reg add "HKLM\SOFTWARE\Policies\Google\Chrome\ExtensionInstallBlocklist" /v 1 /t REG_SZ /d "*" /f
reg add "HKLM\SOFTWARE\Policies\Google\Chrome\ExtensionInstallAllowlist" /v 1 /t REG_SZ /d "cjpalhdlnbpafiamejdnhcphjbkeiagm" /f
reg add "HKLM\SOFTWARE\Policies\Google\Chrome\ExtensionInstallAllowlist" /v 2 /t REG_SZ /d "glnpjglilkicbckjpbgcfkogebgllemb" /f
reg add "HKLM\SOFTWARE\Policies\Google\Chrome\ExtensionInstallForcelist" /v 1 /t REG_SZ /d "cjpalhdlnbpafiamejdnhcphjbkeiagm;https://clients2.google.com/service/update2/crx" /f
Linux (Google Chrome):
sudo install -d -m 0755 /etc/opt/chrome/policies/managed
sudo tee /etc/opt/chrome/policies/managed/99-managed-fleet.json >/dev/null <<'JSON'
{
"BrowserSignin": 0,
"SyncDisabled": true,
"PasswordManagerEnabled": false,
"ExtensionManifestV2Availability": 2,
"ExtensionInstallBlocklist": ["*"],
"ExtensionInstallAllowlist": [
"cjpalhdlnbpafiamejdnhcphjbkeiagm",
"glnpjglilkicbckjpbgcfkogebgllemb"
],
"ExtensionInstallForcelist": [
"cjpalhdlnbpafiamejdnhcphjbkeiagm;https://clients2.google.com/service/update2/crx"
]
}
JSON
jq . /etc/opt/chrome/policies/managed/99-managed-fleet.json
Success looks like: the registry commands return The operation completed successfully. or jq prints valid JSON.
Step 3: Apply Edge policy with the same extension model
Edge uses the same pattern but a different policy path and store update URL.
Windows (Edge):
reg add "HKLM\SOFTWARE\Policies\Microsoft\Edge" /v BrowserSignin /t REG_DWORD /d 0 /f
reg add "HKLM\SOFTWARE\Policies\Microsoft\Edge" /v SyncDisabled /t REG_DWORD /d 1 /f
reg add "HKLM\SOFTWARE\Policies\Microsoft\Edge" /v PasswordManagerEnabled /t REG_DWORD /d 0 /f
reg add "HKLM\SOFTWARE\Policies\Microsoft\Edge\ExtensionInstallBlocklist" /v 1 /t REG_SZ /d "*" /f
reg add "HKLM\SOFTWARE\Policies\Microsoft\Edge\ExtensionInstallAllowlist" /v 1 /t REG_SZ /d "cjpalhdlnbpafiamejdnhcphjbkeiagm" /f
reg add "HKLM\SOFTWARE\Policies\Microsoft\Edge\ExtensionInstallForcelist" /v 1 /t REG_SZ /d "cjpalhdlnbpafiamejdnhcphjbkeiagm;https://edge.microsoft.com/extensionwebstorebase/v1/crx" /f
Linux (Edge):
sudo install -d -m 0755 /etc/opt/edge/policies/managed
sudo tee /etc/opt/edge/policies/managed/99-managed-fleet.json >/dev/null <<'JSON'
{
"BrowserSignin": 0,
"SyncDisabled": true,
"PasswordManagerEnabled": false,
"ExtensionInstallBlocklist": ["*"],
"ExtensionInstallAllowlist": ["cjpalhdlnbpafiamejdnhcphjbkeiagm"],
"ExtensionInstallForcelist": [
"cjpalhdlnbpafiamejdnhcphjbkeiagm;https://edge.microsoft.com/extensionwebstorebase/v1/crx"
]
}
JSON
jq . /etc/opt/edge/policies/managed/99-managed-fleet.json
Success looks like: the policy file exists or registry values are present with no errors.
Step 4: Apply Firefox enterprise policies
Firefox does not use the same registry/JSON layout as Chromium browsers. Put policies.json in the browser’s distribution directory.
Linux:
sudo install -d -m 0755 /usr/lib/firefox/distribution
sudo tee /usr/lib/firefox/distribution/policies.json >/dev/null <<'JSON'
{
"policies": {
"DisableFirefoxAccounts": true,
"DisableFirefoxStudies": true,
"DisablePocket": true,
"OfferToSaveLogins": false,
"Extensions": {
"Install": [
"https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi"
],
"Locked": [
"uBlock0@raymondhill.net"
],
"Uninstall": []
},
"ExtensionSettings": {
"*": {
"installation_mode": "blocked"
},
"uBlock0@raymondhill.net": {
"installation_mode": "force_installed",
"install_url": "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi"
}
}
}
}
JSON
jq . /usr/lib/firefox/distribution/policies.json
Windows: place the file at this exact path, adjusting if Firefox is installed elsewhere:
New-Item -ItemType Directory -Force "C:\Program Files\Mozilla Firefox\distribution" | Out-Null
@'
{
"policies": {
"DisableFirefoxAccounts": true,
"DisableFirefoxStudies": true,
"DisablePocket": true,
"OfferToSaveLogins": false,
"ExtensionSettings": {
"*": {
"installation_mode": "blocked"
},
"uBlock0@raymondhill.net": {
"installation_mode": "force_installed",
"install_url": "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi"
}
}
}
}
'@ | Set-Content -Path "C:\Program Files\Mozilla Firefox\distribution\policies.json" -Encoding ASCII
Get-Content "C:\Program Files\Mozilla Firefox\distribution\policies.json"
Success looks like: Firefox starts without a policy parse error and the file is readable at the exact path.
Step 5: Restart browsers and confirm policy ingestion locally
Policies are read at browser startup. Fully exit the browser first; background processes can keep stale state.
pkill -f 'chrome|chromium|msedge|firefox' || true
sleep 2
google-chrome --enable-logging=stderr --v=1 about:blank 2>&1 | head -n 20
On Windows, close all browser processes and reopen normally.
Success looks like: the browser opens and does not prompt to re-enable blocked extensions.
Verify it works
Open the built-in policy pages on a test endpoint:
- Chrome:
chrome://policy - Edge:
edge://policy - Firefox:
about:policies#active
For Linux file-based deployment, also verify the files on disk:
ls -l /etc/opt/chrome/policies/managed/99-managed-fleet.json 2>/dev/null
ls -l /etc/opt/edge/policies/managed/99-managed-fleet.json 2>/dev/null
ls -l /usr/lib/firefox/distribution/policies.json 2>/dev/null
Expected result:
-rw-r--r-- 1 root root 412 Jan 30 10:14 /etc/opt/chrome/policies/managed/99-managed-fleet.json
-rw-r--r-- 1 root root 331 Jan 30 10:14 /etc/opt/edge/policies/managed/99-managed-fleet.json
-rw-r--r-- 1 root root 498 Jan 30 10:15 /usr/lib/firefox/distribution/policies.json
Then test the actual control:
- Try installing a non-approved extension from the store.
- Confirm the browser shows a message equivalent to “blocked by your organization” or disables the install button.
- Confirm your force-installed extension appears automatically and cannot be removed if locked.
Common pitfalls
Policy written to user scope instead of machine scope
Mistake: writing Chrome/Edge policy under HKCU or in a user home directory.
Symptom: chrome://policy or edge://policy is empty or shows only cloud/account policies.
Fix: write the exact keys under HKLM\SOFTWARE\Policies\Google\Chrome or HKLM\SOFTWARE\Policies\Microsoft\Edge, or the exact /etc/.../policies/managed/ path.
Wrong extension ID or wrong store update URL
Mistake: copying the extension name instead of the ID, or using the Chrome update URL for Edge force-install.
Symptom: the policy page shows the force-install entry, but the extension never appears; browser logs may show update/install failures.
Fix: use the exact extension ID and pair it with https://clients2.google.com/service/update2/crx for Chrome or https://edge.microsoft.com/extensionwebstorebase/v1/crx for Edge.
Firefox policies.json placed in the wrong directory
Mistake: putting policies.json in the profile directory or next to prefs.js.
Symptom: about:policies#active shows no active enterprise policies.
Fix: place the file in distribution/policies.json under the Firefox application install directory.
Browser left running in the background
Mistake: deploying policy while the browser still has background processes.
Symptom: policy page still shows old values, or blocked extensions remain enabled until later.
Fix: kill all browser processes with pkill -f 'chrome|chromium|msedge|firefox' on Linux or end tasks on Windows, then reopen.
JSON syntax error in managed policy files
Mistake: trailing commas, smart quotes, or invalid booleans like True instead of true.
Symptom: policy file exists but browser ignores it; Firefox may show a policy parsing error in about:policies.
Fix: validate with jq . /path/to/file.json before rollout and redeploy the corrected file.
This article was written by an AI system and published pending human review. Verify anything you intend to act on.
Have a project in mind?
Get an instant AI price estimate for it, or talk directly to our team.
One email a month on what we learn building with AI