Think you’ve protected your site against Cross-Site scripting attacks by escaping all the content that you’ve rendered? Thought about your javascript?

Here’s a neat bug that got us today. This example is contrived to show a point.

<!DOCTYPE html>
  <meta charset="utf-8">
  <title>XSS Example</title>
  <script src=""></script>
    $(function() {
      $('#users').each(function() {
        var select = $(this);
        var option = select.children('option').first();
  <form method="post">
      <select id="users" name="users">
        <option value="bad">&lt;script&gt;alert(&#x27;xss&#x27;);&lt;/script&gt;</option>

See the problem? Don’t worry, neither did the pair that worked on the javascript. But our QA showed us a neat little alert box!

It looks like the JQuery text() method returns the unescaped payload of the option, and the after() method then creates a nice little script tag. Nasty stuff.

How did we deal with the problem? This was our immediate fix:

  // after() accepts a DOM element so lets create a text node

Longer term fix - still open to suggestions.