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.

Getting started with the API

Stay organized with collections Save and categorize content based on your preferences.

The Caja Playground is a good place to start for a few lines of JavaScript code or a few URLs, but for integrating your own service with Caja, you want to use the web-based cajoling service. The caja.js API makes it easy to render third-party HTML, CSS and JavaScript safely and easily on your page. We show the steps as they are described in the About Caja page.

Create guest code

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

<html>
  <head></head>
  <body>
    <div>Static hello world</div>
    <div id="dynamicContent"></div>
    <script type="text/javascript">
      document.getElementById('dynamicContent').innerHTML = 'Dynamic hello world';
    </script>
  </body>
</html>

When directly displayed, after the included script runs, this file should look like:

Static hello world
Dynamic hello world

Create host page

Now create a simple host page that looks like the following:

<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">
      caja.initialize({
        cajaServer: 'https://caja.appspot.com/',
        debug: true
      });
      caja.load(document.getElementById('guest'), undefined, function(frame) {
        // will add more here...
      });
    </script>
  </body>
</html>

This code embeds the Caja subsystem by linking to caja.js, and connects it to the Caja server by calling caja.initialize. It specifies the debug option, which makes Caja serve its files un-minified for easier troubleshooting; you should omit this option for production work.

Having declared an HTML DIV for the guest code, identified by guest, the code uses caja.load to construct a sandbox inside that DIV, ready to receive guest code. Caja invokes the callback with a handle to the sandbox, which we call frame.

Run the guest code

Add to the host page the following:


<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">
      caja.initialize({
        cajaServer: 'https://caja.appspot.com/',
        debug: true
      });
      caja.load(document.getElementById('guest'), undefined, function(frame) {
        frame.code('https://developers.google.com/caja/demos/gettingstarted/guest.html',
                   'text/html')
             .run();
      });
    </script>
  </body>
</html>

The complete host page is available here. This code tells Caja to cajole your guest code and run it in the DIV you provided. Running your host page should give you a result like this:

Run it yourself

Review

  • You included Caja in a host page;
  • You used Caja to embed untrusted guest content in the page while protecting yourself from common attacks;
  • The guest content was able to display static HTML; and
  • The guest content also ran JavaScript, including scripts that modify its DOM, using the document object in a standards-based fashion as though it were in its own separate Web page.

Next steps