⏱️ Reading time: 13 min
An IT administrator can block extensions, turn off password saving, and force updates across thousands of machines without touching a single device: Firefox Enterprise policies do that with a JSON file of just a few lines.
📑 En este artículo
Mozilla documents them as part of its Firefox Enterprise offering, designed for companies that need to audit and control the browser across the entire organization. The actual mechanism behind that promise isn’t some mysterious console, it’s a file called policies.json that Firefox reads on startup.
TL;DR
- policies.json is a configuration file that Firefox reads at startup and applies before showing any window.
- Windows uses ADMX templates via Group Policy or Intune; macOS and Linux read the same JSON from a system folder.
- Policies locked with
Locked:truecan’t be reverted from about:preferences, even with local administrator permissions. - about:policies shows in real time which directives are active and whether there were syntax errors when loading the file.
- Mozilla’s policy-templates repository on GitHub documents every valid key, from updates to certificates.
What Are Firefox Enterprise Policies?
Firefox Enterprise policies are a set of JSON directives that Mozilla exposes so an administrator can configure, lock, or deploy browser settings on every machine in an organization, without relying on each user’s graphical interface. They’re defined in a policies.json file or through ADMX templates and MDM.
The engine that interprets them is called the Enterprise Policy Engine, and it’s been built into Firefox since version 60, released in 2018. It’s not a separate product you need to install. Any official Firefox desktop build, Windows, macOS, and Linux, already knows how to read this file; Firefox for Android still doesn’t support policies.json.
Mozilla’s policy-templates repository on GitHub is the canonical reference: it holds the ADMX/ADML templates for Windows, the profiles for macOS, and the documentation for every valid JSON key, with ready-to-copy examples.
Why It Matters
A company that doesn’t control its browser doesn’t control its largest attack surface. The browser is where employees paste credentials, upload files to external services, and run third-party extensions with access to every open tab.
Mozilla built its Enterprise proposition around concrete regulatory frameworks: DORA and NIS2 in the European Union, GDPR for personal data, and ISO 27001 and SOC 2 for operational security controls. None of these frameworks require a specific browser, but all of them require being able to demonstrate which controls exist and audit them. In practice, policies.json is a direct way to generate that evidence: a Git-versioned file that an auditor can read line by line.
There’s also a technical independence argument that Mozilla repeats on its own site: unlike a Chromium-based browser, Firefox runs its own engine, Gecko, so a vulnerability in Chrome’s engine doesn’t automatically affect a company’s Firefox fleet. Diversifying the browser engine reduces the risk of a single exploit taking down every machine at once.
How policies.json Works Under the Hood
When Firefox starts, before loading any user profile, it looks for the policies.json file at a fixed path on the operating system. If it finds it and the JSON is valid, it applies each key as a directive: hiding a menu, forcing a value, or locking a preference so the user can’t change it, not even from about:config.
The path varies by system:
- Windows: the
distributionfolder next to the executable (C:\Program Files\Mozilla Firefox\distribution\policies.json), or directly via Group Policy with the ADMX templates imported into the domain. - macOS:
/Applications/Firefox.app/Contents/Resources/distribution/policies.json, or a configuration profile distributed via MDM. - Linux:
/etc/firefox/policies/policies.jsonon Debian and Ubuntu, or/usr/lib/firefox/distribution/policies.jsonon other distributions, depending on how the browser was packaged.
Every valid policies.json must have the root key "policies". Without it, Firefox also ignores the entire file, just as it does with malformed JSON. Inside that root key go the dozens of directives documented in policy-templates, from trivial settings (Homepage, NewTabPage) to deep security controls (SSLVersionMin, DisableSafeMode). There’s no need to declare the ones you don’t care about. Firefox applies only the keys present and leaves the rest at their default value.
flowchart TD
A["Firefox starts"] --> B["Looks for distribution/policies.json"]
B --> C{"File valid?"}
C -->|"yes"| D["Enterprise Policy Engine applies each key"]
C -->|"no, broken JSON"| E["Ignores the file and logs the error"]
D --> F["User profile loads with restrictions active"]
Practical Examples
The simplest possible policies.json disables a single feature. This example blocks automatic updates, useful when the IT team prefers to manually push tested versions:
{
"policies": {
"DisableAppUpdate": true
}
}
After restarting Firefox and opening about:preferences#general, the updates section disappears completely: there’s no button or message, because the key was locked before the interface was drawn.
A more realistic case combines several directives into an extension policy. This configuration allows only one specific extension and blocks installing any other:
{
"policies": {
"ExtensionSettings": {
"*": {
"installation_mode": "blocked"
},
"[email protected]": {
"installation_mode": "force_installed",
"install_url": "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi"
}
}
}
}
With this policy, the add-ons menu (about:addons) no longer has a button to browse more add-ons, and any attempt to drag a .xpi file into the browser fails with a notice that installation is blocked by organization policy.
The third example combines network and certificate control, typical in companies that inspect TLS traffic with a corporate proxy:
{
"policies": {
"Certificates": {
"ImportEnterpriseRoots": true,
"Install": ["proxy-ca-corporativa.crt"]
},
"DNSOverHTTPS": {
"Enabled": false,
"Locked": true
}
}
}
ImportEnterpriseRoots tells Firefox to trust the root certificates already installed in the operating system’s store, instead of using only Mozilla’s own store. DNSOverHTTPS disabled and locked prevents an employee from re-enabling it from about:config to bypass corporate DNS inspection.
Getting Started
Dependencies before you start: Firefox 60 or later installed (any current version meets this), administrator or root permissions on the machine where you’re testing, and a text editor to write valid JSON.
On Linux, the most direct path is to create the policies folder and the file by hand:
sudo mkdir -p /etc/firefox/policies
sudo tee /etc/firefox/policies/policies.json > /dev/null <<'EOF'
{
"policies": {
"DisableTelemetry": true,
"OverrideFirstRunPage": ""
}
}
EOF
After saving the file, close all Firefox windows and reopen it. To confirm the policy loaded, go to about:policies: the “Active Policies” tab should list DisableTelemetry and OverrideFirstRunPage with the exact value you set in the file. If the JSON has a syntax error, that same screen shows a warning in the “Errors” tab instead of applying anything.
On Windows, the equivalent without a domain is to copy the same file to the distribution folder inside Firefox’s installation directory; with a domain, you import the ADMX templates from the policy-templates repository into the Group Policy console and configure them from there. On macOS, the file goes in /Applications/Firefox.app/Contents/Resources/distribution/policies.json, or it’s packaged as a configuration profile to distribute via MDM.
💡 Tip: about:policies also has a “Documentation” tab with the full JSON schema for the installed Firefox version: useful for validating key names without leaving the browser.
Real-World Use Cases
Mozilla groups the policies most requested by regulated companies into a handful of scenarios, documented on its Firefox Enterprise page:
- Data Loss Prevention (DLP): the
WebsiteFilterkey or extensions managed viaExtensionSettingscan warn about or block actions toward unauthorized domains. - AI tool control: combining
ExtensionSettingsandWebsiteFilter, IT can allow, restrict, or fully disable access to AI chatbots from the corporate browser. - Lockdown mode: hardens the browser for high-risk profiles, restricting script execution on untrusted sites.
- SIEM integration: Firefox can export browser events, such as downloads or extension installations, to a SIEM collector for centralized auditing.
- Extension governance: an organization-wide allowlist or blocklist, just like the uBlock Origin example from the previous section, but applied to hundreds of machines at once.
Common Mistakes and Best Practices
The most frequent mistake is malformed JSON. One extra comma or an unclosed brace is enough to break it. Firefox doesn’t warn you with a dialog box, it simply ignores the entire file and starts up with no policy applied. The only way to catch it is to check about:policies after every change, never assume that because the file exists, it’s being used.
Another common mistake is confusing the distribution folder (where policies.json lives) with the user profile folder (~/.mozilla/firefox/xxxxxxxx.default): they’re different paths, and putting the file in the second one has no effect.
In Windows domain environments, precedence order matters. Group Policy always wins over a local policies.json if both define the same key. If a policy seems not to apply, the first thing to check is whether a domain GPO is overriding it.
Best practice: use Locked:true only on keys that genuinely need to prevent the user from changing them. Locking preferences that the user legitimately needs to adjust, like language or zoom, generates unnecessary support tickets.
⚠️ Heads up: policies.json doesn’t encrypt or hide its contents. Any user with read access to the file system can open the file and see exactly what restrictions it has; it’s not a security-through-obscurity mechanism, it’s declared configuration.
Comparison With Alternatives
Not every company needs the same distribution mechanism. The table below summarizes when each path makes sense, from a standalone policies.json to the full on-premises offering Mozilla advertises on its site.
| Option | When to Use It | Advantage | Limitation |
|---|---|---|---|
| Local policies.json | Standalone machines, no domain, quick tests | No extra infrastructure needed, version-controlled in Git | The file has to be distributed by hand or with a custom script |
| Group Policy (ADMX) on Windows | Companies with Active Directory already deployed | Centralized, automatic application across the entire organizational unit | Only covers domain-joined Windows machines |
| MDM Profile (macOS / Intune) | Corporate laptop fleets with existing MDM | Integrates with the same pipeline that manages the rest of the device | Requires an MDM solution already purchased and configured |
| Firefox Enterprise on-premises | Regulated organizations that don’t want to depend on third-party infrastructure | Console, data, and policies run on your own infrastructure | Mozilla hasn’t yet published pricing or a general availability date |
Going Deeper: Precedence and the Policy Engine
Underneath policies.json runs the same engine, the Enterprise Policy Engine, regardless of whether the source is the JSON file, a Windows GPO, or a macOS MDM profile: all of them end up converted to the same internal structure before being applied. That’s what allows mixing sources without rewriting platform-specific code.
When two sources define the same key, the one with the higher administrative hierarchy wins, not the one loaded last. On Windows, the order is machine GPO, then user GPO, and finally local policies.json. On macOS and Linux, since there’s no GPO, policies.json is the highest-hierarchy source available outside of an MDM.
flowchart LR
A["Windows machine GPO"] --> D["Enterprise Policy Engine"]
B["Windows user GPO"] --> D
C["Local policies.json"] --> D
E["macOS MDM profile"] --> D
D --> F["Final configuration applied to the browser"]
Before 2018, Mozilla solved this with autoconfig, .cfg files with embedded JavaScript, a much more fragile mechanism: a JavaScript syntax error could break the browser’s entire startup, while an invalid policies.json is simply ignored. The switch to declarative JSON was, in large part, a response to years of bug reports for that exact reason.
One real limitation: policies.json doesn’t support conditional logic. There’s no way to say “apply this policy only if the user belongs to group X” inside the file itself; that segmentation has to happen outside it, generating a different policies.json per group and distributing the right one with whatever configuration management tool the company already uses, whether Ansible, Puppet, or Intune.
Since policies.json lives on the file system without its own cryptographic signature, integrity depends on who can write to that folder. An attacker with write access to distribution/ could, in theory, force Certificates.ImportEnterpriseRoots or disable DNSOverHTTPS to facilitate a man-in-the-middle attack. That’s why the usual recommendation is to treat that folder with the same permissions as a system binary. Only a root account or configuration management service account should be able to modify it, never the end user.
Your next step: create a policies.json with a single key like DisableTelemetry on a test machine and confirm the result in about:policies before touching a production machine.
Frequently Asked Questions
What happens if policies.json has a syntax error?
Firefox ignores the entire file and starts up with no policy applied, without showing an error dialog box. The way to detect it is to check the “Errors” tab in about:policies.
Do Firefox Enterprise policies work without Active Directory?
Yes. policies.json is a local file that Firefox reads even if the machine isn’t joined to any domain. Group Policy and MDM are additional layers, not a requirement.
Are policy-templates and policies.json the same thing?
No. policies.json is the configuration file itself. policy-templates is Mozilla’s GitHub repository that documents every valid key and provides the ADMX templates to import those same keys into Group Policy.
Can a user revert a policy locked in policies.json?
No, if the key has Locked:true. The option to change it doesn’t appear in about:preferences or about:config; it stays fixed until an administrator modifies the file.
Does Firefox for Android support policies.json?
No, as of this writing, Enterprise Policy Engine support is limited to desktop versions: Windows, macOS, and Linux.
References
- Firefox.com, official Firefox Enterprise page: describes the on-premises offering, native DLP, and the regulatory frameworks it covers.
- Mozilla’s policy-templates repository on GitHub: complete documentation of every JSON key and the official ADMX/ADML templates.
- Mozilla Support: official support center with configuration guides for IT administrators.
- Wikipedia: Firefox: context on the Gecko engine and the history of Mozilla’s browser.
📱 Enjoying this content? Follow @programacion on Telegram for daily tech content in Spanish: quick summaries, fresh content every day.
Featured image: Foto de ThisisEngineering en Unsplash
Did it work for you? Got a different error? Say so below: questions get answered and help the next reader.
Leave a comment
0 Comments