JavaScript and CSS Block Encoding: Broken by design · 1 September 2010, 14:44

Background:

While discussing possible server-side answers to the Cross-origin CSS exploit, a potential solution that struck me was to capture the server-side script output and filter (, ), { and } into their HTML encoded equivalents.

Since these elements have no meaning in HTML and cannot be used as part of HTML keywords (tags or attributes), it stood to reason that the only thing I could catch with such a filter were non-HTML characters in the first place.

While that was true, inline JavaScript and inline CSS blocks… broke.

Hypothesis:

CSS and JavaScript block handling is broken by design. While they’re embedded in an HTML document, they are handled differently than text in that they are ‘rendered’ (= passed along to the engine that analyses them) as-is.

From my understanding of encoding, encoding should always be applied given the output context. If your server-side script echoes JavaScript (= not HTML) in an HTML context, then it should be encoded with htmlspecialchars() or comparable.

Except… this breaks it.

The greater hilarity is that XHTML/XML complains if you don’t encode it, hence the necessity of using CDATA blocks to wrap one’s JavaScript.

So, this seems a bit schizophrenic to me. A bit, as I’ve said, broken by design. Presumably, the result of the entire conglomerate JS/CSS/HTML’s historic growth and a desperate attempt to patch up what would otherwise be a terrible security issue in code that doesn’t conform:

alert("<?php echo $_POST['something'] ?>");

…would render, with $_POST[‘something’] containing &quot;);eval(blub); // as:

alert("&quot;);eval(blub); //");

…which would be passed to the JS interpreter (in a perfect world) as:

alert("");eval(blub); //");

That looks terrible until you realise that in this perfect world, you would also never not escape your entire JS-Block in an HTML context, and you’d end up with:

alert(&quot;&amp;quot;);eval(blub); //&quot;);

Which would be passed to the JS engine as:

alert("&quot;);eval(blub); //");

Which is exactly what you’d want.

[Note: For the perceptive: Yes, you’d also never do alert("<?php echo $_POST['something'] ?>");, either, you’d alert("<?php echo javascript_encode($_POST['something']); ?>");, but this article is about HTML encoding, and that would still have to be done on the entire block.]

But alas… that’s not how it works. :( And so we’re stuck with this, instead.

— Neike Taika-Tessaro

---

Comment

Textile Help
Categories: bugisms, client-side, confusion, css, development, html, javascript, philosophy, questions, server-side
Related:

Apache & PHP: Headache with POST / GET · 10 December 2011, 02:43

Dear Google · 15 April 2010, 16:27

mediawiki's Special: Recent Changes bug · 30 November 2009, 15:04

Extending phpDocumentor with custom tags · 23 October 2009, 19:36

Profanity and morality · 9 February 2009, 19:22