phptal / PHPTAL

PHP Template Attribute Language — template engine for XSS-proof well-formed XHTML and HTML5 pages
http://phptal.org
GNU Lesser General Public License v2.1
176 stars 42 forks source link

Auto-escaping HTML end tags in CDATA blocks #39

Open dernelson opened 9 years ago

dernelson commented 9 years ago

PHPTAL currently escapes HTML end tags within CDATA blocks, making it impractical to pass through embedded client-side templates:

<script type="text/x-template">/*<![CDATA[*/
    <p>Hello World</p>
/*]]>*/</script>

After executing the PHPTAL template containing this markup, PHPTAL converts the </p> into <\/p>, which botches the markup, and the client-side template fails to render properly.

kornelski commented 9 years ago

HTML now has a <template> tag for this.

Also I think in X(HT)ML output mode content of the <script> would allow unmodified elements.

dernelson commented 9 years ago

We are using HTML5 output mode, and the contents of the template are written in a different language (currently using underscore's templating with default ERB-style delimiters). PHPTAL fails to parse the content if it isn't wrapped in a CDATA block:

exception 'PHPTAL_ParserException' with message 'Invalid tag name '%-''

Isn't the correct behavior here for PHPTAL to output CDATA block contents unmodified?

kornelski commented 9 years ago

Right, I suppose PHPTAL's CDATA escaping should be relaxed and don't escape </ unnecessarily.


In the input the XML rules apply everywhere, even in <script>, so <script> <foo </script> is an XML error, and should be &lt;foo or <![CDATA[<foo]]>.

In HTML the <script> CDATA is special - it doesn't support escaping! So <SCRIPT> <foo </SCRIPT> is fine as-is.

The trick is when you want to write in HTML <SCRIPT>document.write('</script>');</SCRIPT>. Since HTML CDATA doesn't have escape character, the only way to escape it is to use JavaScript escaping (and just hope that everything in script is a JS string and ignore edge cases like if (1 </regex literal/).

HTML4 used to have a rule that </ is not allowed anywhere in CDATA, and that's what PHPTAL sticks to.

I haven't checked in a while, but I vaguely remember that HTML5 relaxed this that only </script is not allowed, but </foo is fine.