Welcome, guest Sign In

What are Caja's Limitations?

This section describes various things that don't work in Caja, along with some workarounds. Some of these are deliberately not supported, some are accidentally not supported. The following material is specific to our Caja instance. Caja has a flexible configuration, so you might not see exactly the same behavior elsewhere.

Server-Side vs. Client-Side Sanitization

Caja has two similar but distinct HTML sanitization processes:

  • Server-side sanitization is the full cajoler transformation applied to your application. Server-side sanitization supports complex features like scripts and stylesheets.
  • Client-side sanitization happens when you set innerHTML in your application. Client-side sanitization is more restrictive, and will silently strip out scripts and stylesheets.

XHTML Strictness

If your application starts with an <?xml> tag or a <!DOCTYPE> that isn't HTML, then Caja will parse your application as XML, which is stricter than HTML, and stricter than what browsers will usually do.

Most of the time, it's easier to tell Caja that your app is HTML. Either omit <!DOCTYPE>, or use some HTML doctype, such as <!DOCTYPE html>.

However, if you do want XHTML strictness, here are some common problems you might encounter:

  • Unclosed tags or unbalanced tags are fatal errors, which will prevent your application from rendering at all.
  • The <script> elements are not special. In HTML, a <script> element will read everything as literal text until a closing </script> tag, so you don't have to do anything about "<" or "&" characters in your script. In XML, a <script> element is parsed like any other tag, and the contents must be well-formed XML. So, you will usually want to quote your script bodies with <![CDATA[...]>.

HTML Limitations

<a target=...>

We allow target=_blank and target=_top. Other values are deleted with a warning. Omitting target is the same as target=_top.

<embed>

For Flash, use <yml:swf> instead. Other embeds are not supported.

<head>

All contents of the head element are stripped. Use plain HTML starting from inside the body.

<iframe>

Not supported yet. Workaround depends on what you're trying to do.

<link rel=stylesheet>

External stylesheets are not supported yet. Workaround is to inline the stylesheet.

<object>

For Flash, use <yml:swf> instead. Other embeds are not supported.

<script>

Inline scripts are supported by the server-side cajoler, but they're stripped by the client-side sanitizer. Workaround depends on what you're trying to do.

<script src=...>

External scripts are not supported yet. Workaround is to inline the script.

<style>

Stylesheets are supported by the server-side cajoler, but they're stripped by the client-side sanitizer. Workaround depends on what you're trying to do.

javascript:void(0)

Caja currently rejects any javascript: URLs.

If you're trying to use javascript:void(0) to make <a> buttons, try using an onclick handler instead, something like this:

URL policy

We currently allow http, https, and mailto URLs.

This applies to any use of URLs, such as <a>, <img>, etc.

CSS Limitations

[] selectors

A subset of [] selectors are supported, but only to the extent that the browser supports them. For example, IE7 will still ignore [] selectors.

expression()

Not supported. Workaround depends on what you're trying to do.

@import

Not supported yet. Workaround is to inline the stylesheet.

:visited

The text-decoration property of :visited is not supported. The following properties are supported: color, background-color, cursor.

JavaScript limitations

eval()

Not supported. Workaround depends on what you're trying to do.

new Function()

Not supported. This is similar to eval. Workaround depends on what you're trying to do.

Assigning strings as event handlers

Code like this is not supported:

That's an implicit eval, and has the same problem as explicit eval.

Instead, put your event-handling code in a function, and assign the function to the event handler:

Names ending with underscore

You can't use names ending with triple-underscore. Those are reserved for Caja's internal bookkeeping.

You can't use names ending with double-underscore. Those are reserved for browser extensions.

with (obj) { ... }

This is not allowed since the dynamic behavior of with makes it difficult to analyze its security implications. The workaround is to remove the with statement and write obj.foo instead of just foo.

Calling a method as a function

If obj.foo is a method that refers to this, then peeling it off as a function and calling it directly will cause a runtime error:

That doesn't really work in raw JavaScript either, but instead of silently doing the wrong thing, Caja will throw an error:

The reason is, JavaScript doesn't have bound methods, so that code probably doesn't do what you want. The code is saying to call getElementById with this bound to the global object, which is window. So if it succeeded, getElementById would get this===window, instead of this===document.

The usual way of capturing a method as a function is to wrap the method call in a function:

And that will work with or without Caja.

select.length

select.length is not usable.

DOM Limitations

Many of the holes in the DOM interface are currently due to missing implementation, rather than security concerns. In general, if the function or property you're trying to use isn't supported, you might be able to do the same thing using interfaces that are supported.

document.write()

Not supported yet. document.write can install malware, and it's difficult to make a safe version that duplicates the way it handles partial HTML fragments.

Instead, use innerHTML:

You can also build up a DOM tree in pieces using document.createElement and so forth.

window.event

window.event isn't supported. This problem shows up if you have event-handling code like this:

When you click on the text, the value you get will be undefined.

The workaround is to pass in the event as an argument. Caja always binds event within onevent= handlers, so you can rewrite the example this way:

Another workaround is to use addEventListener instead.

Table of Contents

Copyright © 2010 Yahoo! Inc. All rights reserved. Copyright | Privacy Policy | Terms of Use

Help us continue to improve the Yahoo! Developer Network: Send Your Suggestions