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.

Providing services to guest code

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

Having learned how to embed guest code and protect yourself from attacks, your next step is to learn how to provide services to the code such that it can interact with your host page.

Create guest code

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

<html>
  <head></head>
  <body>
    <input type="button" id="theButton" value="Say hello">
    <script type="text/javascript">
      document.getElementById('theButton').onclick = function() {
        sayHello();
      };     
    </script>
  </body>
</html>

When directly displayed, this file should look like:

The code you have created refers to the function sayHello. This is a function that your guest code will expect the container to provide; it represents a very simple contract whereby the guest code may ask its host page to perform services.

Create host page

Now create your host page as before like this:

<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/providingservices/guest.html',
                   'text/html')
             .run();
     });
    </script>
  </body>
</html>

Pressing the Say hello button does nothing at this point, since we have yet to provide the guest code with that function.

Provide tame services

Now 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">
      function alertGreeting() { alert('Hello world'); };
      caja.initialize({
        cajaServer: 'https://caja.appspot.com/',
        debug: true
      });
      caja.load(document.getElementById('guest'), undefined, function(frame) {
        caja.markFunction(alertGreeting);
        var tamedAlertGreeting = caja.tame(alertGreeting);
        frame.code('https://developers.google.com/caja/demos/providingservices/guest.html',
                   'text/html')
             .api({ sayHello: tamedAlertGreeting })
             .run();
     });
    </script>
  </body>
</html>

The complete host page is available here. The new code uses the caja object to tame the function alertGreeting. This is done by first telling Caja to allow guest code to call it as a function, via markFunction, then returning a tamed version of the function by calling tame. It then supplies this function as an API to the guest code, via the api() function of the frame, under the name sayHello.

Loading the host page and pressing the button should give you a result like this:

Run it yourself

Review

  • You created an API so that guest content can invoke services from your host page; and
  • The guest content was able to invoke the services by calling a function with an agreed-upon name.

Next steps