Information Flow Control for the Web


A modern browser acts more or less like an operating system, executing programs (or called scripts in the web context) sent from various web sites or stakeholders, while offering a powerful API to these scripts. Because of this API, purely static web pages have evolved from purely static web pages to full-blown web application that dynamically render interactive content. The overall conclusion is that the web is a very influential application platform whereby the technological complexity makes it vulnerable in many ways.

Despite several baked-in countermeasures within your browser, many important attacks remain possible:

Many attack techniques are well understood, but new ones can be expected to surface. It is evident that there is a clear need for robust security techniques that allow the use of such third-party scripts (as they are fundamental of the current web) within the web context, without the accompanying risks (or as little as possible).

This is the essential key driver for our research. We tried to tackle the problem by designing robust security countermeasures for web applications that provide strong security guarantees, without limiting (all too much) the original functionality, by enforcing secure information flows. An application contains only secure information flows if trusted, or private, information entered within an application, doesn’t leak to untrusted sources, a natural notion of security.

This web page goes into more detail about two important tracks within this research:

  1. The first track was the development of a web browser, FlowFox, that enforces information flow policies on all scripts on a web site. It allows even hostile scripts to function, while preventing private or trusted information to leak to untrusted parties, like ad providers.
  2. The second track was to expand the notion of information flow policies with declassification. We show that such declassification policies are useful on the web with e.g., the support of privacy-friendly web analytics data.

The rest of the document points out how to download and use FlowFox yourself and gives you plenty of examples.


The outcome of this research has been reflected through multiple publications on international conferences and peer-reviewed journals:

  1. Willem De Groef, Dominique Devriese, Nick Nikiforakis, Frank Piessens.
    FlowFox: A Web Browser with Flexible and Precise Information Flow Control. Proceedings of the 19th ACM Conference on Computer and Communications Security (CCS 2012), Raleigh, NC, USA, 16-18 October 2012.
    [ bibtex | paper | presentation ]
  2. Mathy Vanhoef, Willem De Groef, Dominique Devriese, Frank Piessens, Tamara Rezk.
    Stateful Declassification Policies for Event-Driven Programs. Proceedings of the 27th Computer Security Foundations Symposium (CSF 2014), Vienna, Austria, 19-22 July 2014.
    [ bibtex | paper | presentation ]
  3. Willem De Groef, Dominique Devriese, Nick Nikiforakis, Frank Piessens.
    Secure Multi-Execution of Web Scripts: Theory and Practice. Journal of Computer Security, vol. 22, no. 4, pp. 469-509, 2014.
    [ bibtex | paper ]

The research results and its practicalities (including a demo of FlowFox) have been demonstrated and highlighted at the multiple venues, both academical and non-academical, including International School on Foundations of Security Analysis and Design (FOSAD), SPION DTAI/Technical Workshops, For Your Eyes Only (International Conference), Creative Media Days (iMinds Conference), OWASP Belgium Chapter Meeting, WebSand, NESSoS Workshop on Access and Usage Control.


FlowFox is a fully functional web browser that implements a precise and general information flow control mechanism for web scripts based on the technique of secure multi-execution. We demonstrate how FlowFox subsumes many ad-hoc script containment countermeasures developed over the last years. We also show that FlowFox is compatible with the current web, by investigating its behaviour on the Alexa top-500 web sites, many of which make intricate use of JavaScript. The performance and memory cost of FlowFox is substantial (a performance cost of around 20% on macro benchmarks for a simple two level policy), but not prohibitive. Our prototype implementation shows that information flow enforcement based on secure multi-execution can be implemented in full-scale browsers. It can support powerful, yet precise policies refining the same-origin-policy in a way that is compatible with existing websites.

Formal Model

We provide evidence for the security of FlowFox by proving non-interference for a formal model of the essence of FlowFox. The mechanization of the model in PLT Redex is available for download, together with a random testing program and a basic browser model.


We have made a demonstration video to show how FlowFox works in practice:

Stateful Declassification

We propose a novel mechanism for enforcing information flow policies with support for declassification on event-driven programs. Declassification policies consist of two functions. First, a projection function specifies for each confidential event what information in the event can be declassified directly. This generalises the traditional security labelling of inputs. Second, a stateful release function specifies the aggregate information about all confidential events seen so far that can be declassified.

We provide evidence that such declassification policies are useful in the context of JavaScript web applications by showing they support privacy-friendly collection of web analytics data. An enforcement mechanism for our policies is presented and its soundness and precision is proven. Finally, we give evidence of practicality by implementing and evaluating the mechanism in a browser.

Formal Model

PLT Redex is a tool for defining, debugging and testing operational semantics. We provide an implementation of all our operational semantics, as well as automated randomized tests (verifying progress, determinism and security).

Example 1:

Keylogger executed under normal semantics. It is given one input, namely (KeyPress 1), and produces the output (Send 1). Because Redex does not support symbols on state transitions, we have included the input and output lists in the program state itself.

Example 2:

Keylogger executed under SME using a declassification policy treating KeyPresses as high input, and network outputs (Send) as low output. The high input is only handled by the high execution, which can be seen in the second state (the low execution appears first in the state, followed by the high execution). The high execution suppresses output to low observers, and as a result the keylogger has been blocked. Note that the declassification policy D is represented by a functional program (combining the release and project functions) and is shown in red.

Example 3:

The shortcut monitoring program executed under SME. The declassification policy marks network outputs (Send) as low security, KeyPresses as high, and Unload as low, and allows a program to release whether a particular shortcut has been pressed. The program will output (Send 0) if the shortcut hasn’t been used, and (Send 1) if it has been used. The image below contains only parts of the reduction graph. In particular we only show the start state, the state after fully processing the shortcut key press (notice that the policy state is now #f and the value on the release channel is 1), and finally the last state of the execution (where we can see the program under SME has outputted Send 1). The full reduction graph can be viewed here.


Important: When testing a new example, first update the POLICY environment variable to the new .js policy file and restart FlowFox.

Example 1: Shortkey usage

In this example we implement the shortcut key monitoring program:

Example 2: Average Mouse Click

This example declassifies the average of two mouse clicks:

Try Yourself

If you want to play with FlowFox without installing it on your computer, we offer you a LiveCD with FlowFox pre-installed together with some demo scenarios. You only need to download a VirtualBox binary installation file, compatible with your system. Next, download the VirtualBox image with FlowFox pre-installed.

If you are already running Ubuntu, simply install VirtualBox, download the LiveCD and import the image into VirtualBox.


Start by installing Virtualbox:

apt-get install virtualbox-ose

Next, download the FlowFox virtual image:


Third, import the FlowFox virtual image within Virtualbox:

VBoxManage import --vsys 0 --vmname "FlowFox" flowfox.ova

The last step is to start the virtual image:

VBoxManage startvm "FlowFox"

Running FlowFox

After booting, login by clicking on the demo username with password demo.

After logging in, you can start using the virtual machine. At the bottom of the screen, there is a menu bar that allows for direct access to FlowFox, a regular Chromium browser and the policy file for FlowFox.

The policies for FlowFox can rely on a preloaded policy library, for which its source code can be found in /home/demo/flowfox/policy_lib.js. If necessary, it is possible to overwrite this file with your own implementation of a policy file, but this is not required, nor recommended.

Next, there is also a more specific policy file. The file is located in at /home/demo/flowfox/policies.js or you can click on the third icon in the menu bar to open and modify it. After modification, it is necessary to save the file and to reload FlowFox (by refreshing or restarting) to enforce the new policy.

Both a list of possible DOM API calls and other examples of policies, can be found in the demo policy file.

If you want to run FlowFox from command line, you have to manually specify the policy library and the policy file. You can do so by specifying the POLICY_LIB and POLICY environment variables.

export POLICY_LIB=/home/demo/flowfox/policy_lib.js
    export POLICY=/home/demo/flowfox/policies.js
    ./flowfox/firefox -ProfileManager -no-remote

Run the Websand demo

The Websand demo is a demonstration of a possible declassification scenario. In order to try the Websand demo, you also need to start the recording server (a trimmed down version of a tracking server from a web analytics company) by clicking on the fourth icon on the menu bar.

Next, you can launch a regular Chromium browser and visit both the Dashboard page and the Mouse Recording page. Start moving your mouse within the Mouse Recording window. Next go back to the Dashboard page and click on Load. You will see an image of your recorded mouse positions. In the example below, you see that the user drew the shape of the letter W.

The final step is to redo the experiment with FlowFox while enforcing a declassification policy to partially declassify the mouse coordinates. Make sure that the following declassification policy is active:

SME.lowInputEvent("mousemove", {
        "nsIDOMNSUIEvent_GetPageX": function (x) {
                                        return 100*Math.round(x/100);
        "nsIDOMNSUIEvent_GetPageY": function (y) {
                                        return 100*Math.round(y/100);

Open the same Mouse Recording page in FlowFox and start moving your mouse. The result on the Dashboard page should look like something below (clicking on the play button will start a record video of this example):

FlowFox Internals

The basic policy library provides a high-level language on top of the SME primitives that are being used within FlowFox.

Each JavaScript API method available in FlowFox is surrounded with extra SME primitives. These SME primitives should used to enforce the SME I/O rules and their exact implementation is up to the policy developer. Let’s take a look at a fictious example of the document.cookie API implementation:

        if not SME.skipCall("Document_Get_Cookie"):
              res = perform_actual_call()
              return SME.saveData("Document_Get_Cookie", res)
        else: return SME.defaultValue("Document_Get_Cookie")

Although these primitives have powerful potential to modify API behavior, making even a small mistake in the behavior of these primitives can result in weird functioning of both the browser and the JavaScript programs.

Policy Library

The task of the policy library is to free the policy writer from the burden to instrument these primitives and to allow semantically meaningful policies. Under the hood, these calls are translated to enforce the right SME.skipCall, SME.saveData and SME.defaultValue combination. The policy JavaScript library offers for example methods to describe API methods as input operations with a specific security label:

        SME.inputAt(1, function () { return "default value"; }));
    SME.lowInputEvent("click", {
                function (origX) { return Math.floor(origX + Math.random()*11); }),

Take a look at the complete set of policy API methods or the complete list of supported (and thus interruptible) DOM API methods to start writing policies yourself.

The user shouldn’t touch the basic policy library files. He/she can add new rules in a separate file by specifying the POLICY environment variable. The policy library itself can be specified via the POLICY_LIB environment variable. For an example how to load these files, look at Section 1.

Declassification Library

In order for FlowFox to support stateful declassification policies, two major enhancements were added to its code base under the form of the new SME primitive SME.skipEvent and SME.release.

First, before every event gets handled, the release function is called to update a state space to allow the declassify operator within scripts to ‘leak’ or release declassified information. Initially, the policy library contains a dummy implementation as it is up to the policy writer to decide when and how to update the state space.

Second, a project function is offered by the policy library to release (slightly) modified information through API calls belonging to event objects and/or hide the occurrence of events within contexts. Its first argument is the name of the projected event, the second argument is a list of specific rules for API methods relevant for the (object of the) event. For example:

SME.project("click", {
        "nsIDOMMouseEvent_GetClientX": SME.projectedInput(function (origX) { return origX + Math.random() }),
        "nsIDOMMouseEvent_GetClientY": SME.inputAt(1, function () { return 1000 })


A few important remarks when testing FlowFox:

  1. You must run the examples from an actual web server. Files loaded from “file://” are not executed under the SME security mechanism.1
  2. Page reloading is not fully supported. To reload a page close the current tab and open the page in a new tab.
  3. When changing the policy, it is best to restart FlowFox in order to make sure the changes to take effect.


This research and the development of the FlowFox prototype is partially funded by the EU FP7 project WebSand, and by the IWT-SBO project Spion.






  1. In fact the opposite is true. Only JavaScript from pages with an URL starting with “http(s)” are executed under the SME regime.