On January 31st, 2021, we will be archiving the Caja project. After January 31, no new features will be added, pull requests and other issues will no longer be addressed, including patches for security issues, and the repository will be marked as archived. Caja has not been actively maintained or developed to keep up with the latest research on web security. As a result, several security vulnerabilities have been reported to Caja, both by Google’s security engineers and by external researchers.

We encourage users of Caja's HTML and CSS sanitizers to migrate to Closure toolkit, an open source toolkit for Javascript. Closure is used by applications, including Search, Gmail, Docs and Maps.

The Closure library has built-in HTML and CSS sanitizers and provides native support for key security mitigations like Content Security Policy and Trusted Types. Additionally, Closure templates provide a strictly contextual auto-escaping system, which can drastically reduce the risk of XSS in your application.

Controlling network access

The host page you create has full control over the guest code's access to the network. Here's how to take advantage of this.

Create guest code

Assume your third-party guest code is as follows (also available here):

<html>
  <head></head>
  <body>
    <img src="a.png">
    <img src="b.png">
 </body>
</html>

When displayed directly, the page should look like this:

Create host page

Now create your host page as follows (also available here):

<html>
  <head>
    <title>Caja host page</title>
    <script type="text/javascript"
            src="//caja.appspot.com/caja.js">
    </script>
 </head>

  <body>
    <h1>Caja host page</h1>
    <div id="guest"></div>
  <script type="text/javascript">
    var uriPolicy = {
      rewrite: function(uri) {
        if (/a\.png/.test(uri)) { return uri; }
        return undefined;
      }
    };
    caja.initialize({
       cajaServer: 'https://caja.appspot.com/',
       debug: true
     });
     caja.load(document.getElementById('guest'), uriPolicy, function(frame) {
        frame.code('https://developers.google.com/caja/demos/controllingnetwork/guest.html',
                   'text/html')
             .run();
     });
  </script>
  </body>
</html>

The uriPolicy object contains a callback, rewrite, which Caja will invoke whenever guest code attempts to use the network — even to load an image declared in the guest HTML. When you run this code, you will notice that a.jpg is displayed in the HTML because your URI policy returned a.jpg for its URI, but b.jpg is not because your URI policy returned null.

Calls to the URI policy are made directly by Caja to your code. There is no need for any portion of the URI policy to be tamed.

When displayed, the guest page should look like this (note that, consistent with your policy, only the first image is displayed):

Caja invokes your URI policy for all network access initiated by the guest, including image embedding (as demonstrated), hyperlinks; and XMLHttpRequest

Run it yourself

Review

  • You controlled the network access granted to guest code.

Next steps