You are currently viewing a snapshot of www.mozilla.org taken on April 21, 2008. Most of this content is highly out of date (some pages haven't been updated since the project began in 1998) and exists for historical purposes only. If there are any pages on this archive site that you think should be added back to www.mozilla.org, please file a bug.



Configurable Security Policies

What are Configurable Security Policies?

Mozilla's configurable security policies allow users to set up security policies for the browser, and also have different security policies for different Internet sites. The ideas for configurable security policies come from a number of sources. Bell Labs researchers Vinod Anupam and Alain Mayer have written papers and contributed code to Mozilla. The infamous bug 858 serves as a wish list for this sort of functionality. The code for this is called CAPS (capabilities). Finally, IE's zones employ some of this idea.

This document is aimed at programmers familiar with JavaScript.

N.B. As of Mozilla 0.9.9, a "policynames" line is required in order to create zone policies. See below for details.

Setting Global Policies

Suppose you're annoyed by pop-up advertisements and want to prevent all web pages from opening new browser windows. You can do this by adding the following line to your Mozilla user preferences file (user.js):

   user_pref("capability.policy.default.Window.open", "noAccess");

Setting Window.open to noAccess means that web pages can not access the open property of any object of type Window. If a web site tries to open a new window using window.open() (or open()), the attempt will fail. The security manager will throw a JavaScript exception, preventing the function from being called. Unless the web page catches the exception, the script will stop and an error message will appear on the JavaScript console (Tasks->Tools->JavaScript Console).

Zone Policies

The default policy is special; it applies to all sites. You can also set policies that apply to specific sites or groups of sites, overriding the default. For example, if you wanted to restrict www.evil.org and www.annoying.com from creating dialog windows, you could use the following code:

   user_pref("capability.policy.policynames", "strict");
   user_pref("capability.policy.strict.sites", "http://www.evil.org http://www.annoying.com");
   user_pref("capability.policy.strict.Window.alert", "noAccess");
   user_pref("capability.policy.strict.Window.confirm", "noAccess");
   user_pref("capability.policy.strict.Window.prompt", "noAccess");

The first line defines the name of the policy or policies you want to create, in this case "strict". If you define more than one policy, list them all on the same line, like so:

   user_pref("capability.policy.policynames", "strict, shoppingsites, ");

The preference "capability.policy.strict.sites" defines the web sites to which the strict policy is applied. The value of that preference is a list of sites (protocol and hostname only), separated by spaces. The final three lines define the strict policy. For these sites, the example above will disallow access to window.alert(), window.confirm() and window.prompt().

Note that since we haven't defined whether sites under the strict policy can open new windows with window.open(), the default policy still applies.

Suppose we've also discovered that in blocking access to window.open(), we've prevented a script on www.usefulsite.net from working. We can allow this page to bypass the window.open restriction by setting the Window.open policy back to its default value, sameOrigin:

   user_pref("capability.policy.policynames", "trustable");
   user_pref("capability.policy.trustable.sites", "http://www.usefulsite.net");
   user_pref("capability.policy.trustable.Window.open", "sameOrigin");

The name of the policy can be anything you want; we used strict and trustable in this example, but you could name it blacklist or mypolicy or anything else.

Security Levels

There are three special security levels:

  • noAccess: web sites can never access this property or call this function.
  • sameOrigin (default): web sites can access this property, but only for pages on the same site. See this document for an explanation of how Mozilla determines whether two pages have the same origin.
  • allAccess: a web site can access this property within the same site and on any other site.

If the security level is not one of the three above, it is treated as a privilege name, and a script can access it only if the script is signed and the user grants the privilege to the script through a dialog.

Get and Set

You can specify a policy that applies only to reading a property, or only to changing its value, by adding .get or .set after the property name. This allows you to specify one policy for reading a property and another for changing its value. See below for some examples that block pages from setting values but not from reading them.

Setting Class.property.get and Class.property.set to the same level is equivalent to setting Class.property to that level. Don't use get or set after the name of a function (such as open or write); the concept of "get" and "set" applies only to properties which are not functions (such as bgColor or location).

Figuring out Object Names

Figuring out the correct object name to use is sometimes tricky. For example, suppose you want to prevent a web page from submitting a form for you, but you don't know the class name for a form element. The easiest way is to find out is to write a script that converts the object into a string. If you go to a page with a form and type javascript:alert(document.forms[0]) into the location bar, you'll see that document.forms[0] is an [xpconnect wrapped HTMLFormElement]. HTMLFormElement is the name of the class, so you can set HTMLFormElement.submit to noAccess to prevent web pages from submitting forms using form.submit.

Some elements, such as HTMLAnchorElement, have special toString functions that prevent you from finding their class name easily. If you type javascript:alert(document.links[0]) in the location bar, you will see the URL of the first link instead of its class name. The way to get around this problem is to use the default toString function on the object document.links[0], like so: javascript:alert(window.toString.apply(document.links[0])).

Caveat: Some Properties Have Multiple Access Paths

When blocking access to properties, it is important to note that there is more than one way to access some properties, such as attributes of HTML elements. For example, suppose a user wants to prevent scripts from www.evil.org from accessing the href attribute of HTML anchor tags (<A HREF="...">). The following prefs are not sufficient:

   user_pref("capability.policy.policynames", "nohrefs");
   user_pref("capability.policy.nohrefs.sites", "http://www.evil.org");
   user_pref("capability.policy.nohrefs.HTMLAnchorElement.href", "noAccess");

While these prefs will prevent a script on www.evil.org from accessing document.links[1].href, the script can access the very same information using the DOM 2 syntax document.links[1].attributes.getNamedItem("href") or document.links[1].getAttribute("href"). The following prefs will completely block access to the href attribute:

   user_pref("capability.policy.policynames", "nohrefs");
   user_pref("capability.policy.nohrefs.sites", "http://www.evil.org");
   user_pref("capability.policy.nohrefs.HTMLAnchorElement.href", "noAccess");
   user_pref("capability.policy.nohrefs.HTMLAnchorElement.attributes", "noAccess");
   user_pref("capability.policy.nohrefs.HTMLAnchorElement.getAttribute", noAccess");
   user_pref("capability.policy.nohrefs.HTMLAnchorElement.getAttributeNS", "noAccess");

As a general rule, to block access to an attribute, you must also block the attributes property and the getAttribute and getAttributeNS methods.

The Complete Preferences Syntax

Here's a more formal statement of the syntax for JavaScript security policies:

  • A policy consists of a policynames line, a sites line, and one or more policy lines. The sites line must be omitted for the default policy, but it must be present for all others.
  • The policynames line specifies the names of all the policies you want to define. There should be only one policynames line, no matter how many policies you define. It has this format:
    user_pref("capability.policy.policynames", "<list of policy names>"); where <list of policy names> is a list of the policy names you want to define, separated by commas and/or spaces.
  • The sites line has this format:
    user_pref("capability.policy.<policy name>.sites","<URL list>");
    • <policy name> is any combination of letters and numbers, starting with a letter.
    • "<URL list> is a list of URLs separated by spaces. Each URL in the list can either be of the form protocol:, which will apply the policy to all URLs with the given protocol (such as http:), or protocol://host which will apply to a particular host (for example, http://www.annoyingsite.myisp.com). Don't include the path portion of the URL (the / after the host name or anything after it).
  • A policy line has this format:
    user_pref("capability.policy.<policy name>.<class name>.<property name>","allAccess | noAccess | sameOrigin | <capability name>");
    • <policy name> must be the same as the policy name on the sites line.
    • The pref values (allAccess, etc.) are described above.

Disabling All Javascript for a Site

The special property javascript.enabled can be used to disable JavaScript execution, either globally, using the default policy, or for a group of sites, using a site policy. For this special policy, the value of the preference must be "noAccess" or "allAccess". No other values will work. The following example disables all JavaScript execution at site1.com and site2.com:

   user_pref("capability.policy.policynames", "nojs");
   user_pref("capability.policy.nojs.sites", "http://site1.com http://site2.com");
   user_pref("capability.policy.nojs.javascript.enabled", "noAccess");

This example disables JavaScript execution at all sites except goodsite.com:

   user_pref("capability.policy.policynames", "jsok");
   user_pref("capability.policy.default.javascript.enabled", "noAccess");
   user_pref("capability.policy.jsok.sites", "http://goodsite.com");
   user_pref("capability.policy.jsok.javascript.enabled", "allAccess");

Note that only values of "allAccess" or "noAccess" will work for the javascript.enabled policy prefs. Don't use "sameOrigin" or any other string in this case. Also note that this preference:

   user_pref("javascript.enabled", false);

overrides all capability.policy prefs, including capability.policy.default.javascript.enabled, for all sites.

Additional Examples

Prevent web pages from resizing browser windows

   user_pref("capability.policy.default.Window.innerWidth.set", "noAccess");
   user_pref("capability.policy.default.Window.innerHeight.set", "noAccess");
   user_pref("capability.policy.default.Window.outerWidth.set", "noAccess");
   user_pref("capability.policy.default.Window.outerHeight.set", "noAccess");
   user_pref("capability.policy.default.Window.sizeToContent", "noAccess");
   user_pref("capability.policy.default.Window.resizeTo", "noAccess");
   user_pref("capability.policy.default.Window.resizeBy", "noAccess");

Prevent web pages from moving browser windows

   user_pref("capability.policy.default.Window.screenX.set", "noAccess");
   user_pref("capability.policy.default.Window.screenY.set", "noAccess");
   user_pref("capability.policy.default.Window.moveTo", "noAccess");
   user_pref("capability.policy.default.Window.moveBy", "noAccess");

Prevent web pages from finding the your screen resolution and color settings

(Note: these lines don't block all of the ways a web page might find your screen reslution; they only block the most common ones. They don't prevent a web page from finding out how big its window is.)

   user_pref("capability.policy.default.Screen.top", "noAccess");
   user_pref("capability.policy.default.Screen.left", "noAccess");
   user_pref("capability.policy.default.Screen.width", "noAccess");
   user_pref("capability.policy.default.Screen.height", "noAccess");
   user_pref("capability.policy.default.Screen.pixelDepth", "noAccess");
   user_pref("capability.policy.default.Screen.colorDepth", "noAccess");
   user_pref("capability.policy.default.Screen.availWidth", "noAccess");
   user_pref("capability.policy.default.Screen.availHeight", "noAccess");
   user_pref("capability.policy.default.Screen.availLeft", "noAccess");
   user_pref("capability.policy.default.Screen.availTop", "noAccess");

Prevent web pages from changing the text in the status bar

Some web pages create "blind links" by changing the status bar text when you hover over the link, preventing the link address from being show in the status bar. This line will turn most blind links into normal links.

   user_pref("capability.policy.default.Window.status", "noAccess");

User Interface

We still have no user interface for configuring security policies. In the future, we hope to have a panel in preferences that allows the user to set policies without having to manually edit user.js or know JavaScript. This may be the hardest part of the feature to implement. See bug 38966.