Security Policies
Overview
All Mozilla-based applications allow users to restrict (or disable) various security-related settings. These restrictions can be as generic or specific as needed, and can be universally applied or limited to certain protocols and domains. This functionality is collectively known as "Security Policies," "Configurable Security Policies," or "CAPS."
A typical end-user probably won't need much of the advanced functionality CAPS offers. However, there are a few common cases where you would need to use security policies: clipboard access for JavaScript, site whitelists or blacklists for JavaScript functionality, and checkloaduri
policies (using file://
links from remote webpages). Those three cases are explained in greater detail in the linked articles.
Managing Security Policies
There is currently no official dialog-based user interface for managing security policies, although there is an open bug for the functionality. For Mozilla Suite and Firefox, there is a third-party extension called Policy Manager which provides such an interface; it also extends CAPS to allow for configuration of non-JavaScript functionality such as image loading, popups, and cookies. You are limited to a handful of useful options when using the extension, though: you cannot create arbitrary policies through its interface.
If you need more customizability for your security policies, you will need to edit your configuration files. You can also use about:config, but due to a bug, you will not see the changes you've made (though they will take effect). Security policies are specified in preferences, so you should be comfortable editing user.js. A useful extension for making edits is ChromEdit.
Understanding Security Policies
The documentation at mozilla.org is more complete than what's covered below, but this information is aimed at the enthusiast rather than the JavaScript programmer.
All of the examples in this article assume the reader is editing user.js.
Anatomy of a Policy
For a policy to exist, it has to have a name. That name has to be included in the preference capability.policy.policynames, which is a space-separated list of all the custom policies you want to use. This means that if you want to have a policy that allows local file links for sites on your intranet and a separate policy that allows your favorite CMS's copy/paste functionality to work, you'll need to have both listed in this preference:
// "localfilelinks" is a policy to allow links to local files from specific websites // "allowclipboard" is a policy to enable cut/copy/paste from JavaScript user_pref("capability.policy.policynames", "allowclipboard localfilelinks");
Next, we need to specify what the policies actually do (the capabilities). These preferences will vary quite a bit depending on what you want to do, but always take the form capability.policy.<policy name>.<capability>. The functionality we want in our example is described in other articles in detail, but for the sake of brevity here are the capability preferences we need to set for our example:
// Allow file links for the "localfilelinks" policy user_pref("capability.policy.localfilelinks.checkloaduri.enabled", "allAccess"); // Allow cut/copy/paste for the "allowclipboard" policy user_pref("capability.policy.allowclipboard.Clipboard.cutcopy", "allAccess"); user_pref("capability.policy.allowclipboard.Clipboard.paste", "allAccess");
You'll notice that the value we're assigning is "allAccess". In CAPS, these preferences can have one of three values: allAccess (which essentially means "true" or "enabled"), noAccess ("false" or "disabled"), or the rarely-used sameOrigin ("true" or "enabled", but only when working on the same server).
Now our two example policies have names and capabilities defined, but they don't apply anywhere. We need to specify which sites they apply to. This is done by setting the preference capability.policy.<policy name>.sites for each policy, which is also a space-separated list. Thus, if your intranet sites were hosted at http://intranet/ and http://internal/, and your CMS was hosted at http://www.example.com/, you would add these lines:
user_pref("capability.policy.localfilelinks.sites", "http://intranet http://internal"); user_pref("capability.policy.allowclipboard.sites", "http://www.example.com");
And that's it: we now have two fully-defined policies that do different things and apply to certain sites only. You will need to restart the program so your settings are read.
To summarize:
- Each policy needs a name, and all the names should be listed in the preference capability.policy.policynames
- Each policy can have one or more capabilities associated with it, and those preferences take the form capability.policy.<policy name>.<capability>
- Each policy needs to specify what site(s) it applies to, and that information is stored in a preference of the form capability.policy.<policy name>.sites
The Default Security Policy
What if you want your policy to apply to every site automatically? Mozilla comes with one predefined policy for this: the default policy. You don't need to give it a name in capability.policy.policynames (it's built in). The syntax is exactly the same as if you were using one of your own named policies, except it doesn't need a "capability.policy.default.sites" preference.
You can override settings in the default policy with your own policies. This is useful for disabling something but excepting certain sites. For example: in order to disable JavaScript except for certain sites you specify, you would first turn JavaScript off for the default policy:
user_pref("capability.policy.default.javascript.enabled", "noAccess");
Then you would create your own policy to enable JavaScript for certain sites. In the following example, we create a policy named "jsok":
user_pref("capability.policy.policynames", "jsok"); // notice we don't need to name "default" here user_pref("capability.policy.jsok.sites", "http://www.example.com"); user_pref("capability.policy.jsok.javascript.enabled", "allAccess");
In every case, a named policy will override a setting in the default policy.
Note: as mentioned elsewhere, you still need to have JavaScript enabled in the browser for the above example to work. The browser-wide javascript.enabled preference trumps anything set in CAPS.
Other Things Policies Can Do
The examples up to this point have been relatively common tasks, and they haven't touched on the area where CAPS really shines: fine-grained control of what JavaScript is allowed to do. To truly take advantage of these abilities, it really helps to know a bit about JavaScript. The mozilla.org documentation is geared towards those familiar with the language, and it's recommended that you read it. Here, though, we'll dissect one of the examples in that article, as well as give a couple other examples.
Prevent web pages from changing the text in the status bar
This is actually a built-in feature of Mozilla browsers now, and it has its own separate non-CAPS preference: dom.disable_window_status_change. However, maybe you'd like to allow this feature for certain websites. In order to do this, we'll need to first set dom.disable_window_status_change to false, as a setting of true will override any CAPS preferences. Then, it's just a matter of applying the concepts in this article:
// Enable the browser-wide status bar change pref user_pref("dom.disable_window_status_change", false); // Disable window.status changes by default user_pref("capability.policy.default.Window.status", "noAccess"); // Name a new policy for sites that can change window.status user_pref("capability.policy.policynames", "statuschange"); // Define the capability for the policy user_pref("capability.policy.statuschange.Window.status", "allAccess"); // Define the sites that can use this policy user_pref("capability.policy.statuschange.sites", "http://www.fark.com");
Prevent web pages from changing the text in the title bar
This is similar to the above example, but instead of Window.status
as the UI we want to lock down, we want to find out how to stop JavaScript from setting the page's title. A little research tells us that it's done by setting document.title
. So the policy would look like this:
// By default, prevent scripts from setting the title of documents user_pref("capability.policy.default.HTMLDocument.title.set", "noAccess");
Prevent web pages from opening the "Add Bookmark" dialog
One annoying feature of Internet Explorer is the ability for scripts to popup up the "Add Bookmark" dialog without prompting. Mozilla Firefox has a similar "feature," but its limitation is that by default the bookmark is set to open in the sidebar. (This is because it is part of a set of JavaScript functions for the sidebar, most of which are deprecated.) For this reason, not very many sites use it. It's still annoying, though, and it can be disabled via CAPS:
user_pref("capability.policy.policynames", "sidebarAccess"); // Disable sidebar-associated functions, including addPanel() user_pref("capability.policy.default.Window.sidebar", "noAccess"); // Allow mozilla.org and mycroft to add search engine plugins user_pref("capability.policy.sidebarAccess.sites", "http://www.mozilla.org http://mycroft.mozdev.org"); user_pref("capability.policy.sidebarAccess.Window.sidebar", "allAccess");
Prevent web pages from triggering File → Print
In JavaScript, web pages can trigger the Print dialog via window.print()
. This is sometimes annoying (and a little insulting), so you can disable this with another policy:
user_pref("capability.policy.default.Window.print", "noAccess");
Prevent any JavaScript function/member from being run/read/set
CAPS policies can apply to JavaScript functions and variables defined in web pages, too. When a web page author defines their functions and variables in the global scope, those functions and variables actually become methods and members of the Window
object. This means it's a simple matter to pick off individual functions from web pages that annoy you:
user_pref("capability.policy.policynames", "killfunction killvariable"); user_pref("capability.policy.killfunction.Window.nameOfFunction", "noAccess"); user_pref("capability.policy.killfunction.sites", "http://www.example.com"); user_pref("capability.policy.killvariable.Window.nameOfVariable.set", "noAccess"); user_pref("capability.policy.killvariable.Window.nameOfVariable.get", "noAccess"); user_pref("capability.policy.killvariable.sites", "http://www.example.com");
Disable form focusing
Web pages can automatically focus a form when a page loads. To disable this for specific sites:
user_pref("capability.policy.policynames", "nofocus"); user_pref("capability.policy.nofocus.sites", "http://www.example.com"); user_pref("capability.policy.nofocus.HTMLInputElement.focus", "noAccess");
See also
- Allowing only certain sites to use JavaScript
- Granting JavaScript access to the clipboard
- Links to local pages don't work