On Nov 1, 2012, at 1:57 PM, Adam Barth <w...@adambarth.com> wrote:

> 
> 
> (5) The nested template fragment parser operates like the template fragment 
> parser, but with the following additional difference:
>      (a) When a close tag named "+script" is encountered which does not match 
> any currently open script tag:
> 
> Let me try to understand what you've written here concretely:
> 
> 1) We need to change the "end tag open" state to somehow recognize 
> "</+script>" as an end tag rather than as a bogus comment.
> 2) When the tree builder encounter such an end tag in the ???? state(s), we 
> execute the substeps you've outlined below.
> 
> The problem with this approach is that nested templates parse differently 
> than top-level templates.  Consider the following example:
> 
> <script type=template>
>  <b
> </script>
> 
> In this case, none of the nested template parser modifications apply and 
> we'll parse this as normal for HTML.  That means the contents of the template 
> will be "<b" (let's ignore whitespace for simplicity).
> 
> <script type=template>
>   <h1>Inbox</h1>
>   <script type=template>
>     <b
>   </+script>
> </script>
> 
> Unfortunately, the nested template in this example parses differently than it 
> did when it was a top-level template.  The problem is that the characters 
> "</+script>" are not recognized by the tokenizer as an end tag because they 
> are encountered by the nested template fragment parser in the "before 
> attribute name" state.  That means they get treated as some sort of bogus 
> attributes of the <b> tag rather than as an end tag.

OK. Do you believe this to be a serious problem? I feel like inconsistency in 
the case of a malformed tag is not a very important problem, but perhaps there 
are cases that would be more obviously problematic, or reasons not obvious to 
me to be very concerned about cases exactly like this one.

Also: can you think of a way to fix this problem? Or alternately, do you 
believe it's fundamentally not fixable? I've only spent a short amount of time 
thinking about this approach, and I am not nearly as much an expert on HTML 
parsing as you are.


>  
>          (a.i) Consume the token for the close tag named "+script".
>          (a.ii) Crate a DocumentFragment containing that parsed contents of 
> the fragment.
>          (a.iii) [return to the parent template fragment parser] with the 
> result of step (a.ii) with the parent parser to resume after the "+script" 
> close tag.
> 
> 
> This is pretty rough and I'm sure I got some details wrong. But I believe it 
> demonstrates the following properties:
> (B) Allows for perfect fidelity polyfills, because it will manifestly end the 
> template in the same place that an unaware browser would close the <script> 
> element.
> (C) Does not require multiple levels of escaping.
> (A) Can be implemented without changes to the core HTML parser (though you'd 
> need to introduce a new fragment parsing mode).
> 
> I suspect we're quibbling over "no true Scotsman" semantics here, but you 
> obviously need to modify both the HTML tokenizer and tree builder for this 
> approach to work.

In principle you could create a whole separate tokenizer and tree builder. But 
obviously that would probably be a poor choice for a native implementation 
compared to adding some flags and variable behavior. I'm not even necessarily 
claiming that all the above properties are advantages, I just wanted to show 
that there need not be a multi-escapting problem nor necessarily scary 
complicated changes to the tokenizer states for <script>.

I think the biggest advantage to this kind of approach is that it can be 
polyfilled with full fidelity. But I am in no way wedded to this solution and I 
am intrigued at the mention of other approaches with this property. The others 
I know of (external source only, srcdoc like on iframe) seem clearly worse, but 
there might be other bigger ones.

>  
> (D) Can be implemented with near-identical behavior for XHTML, except that 
> you'd need an XML fragment parser.
> 
> The downside is that nested templates don't parse the same as top-level 
> templates.  

Indeed. That is in addition to the previously conceded downsides that the 
syntax is somewhat less congenial.

> Another issue is that you've also introduced the following security risk:
> 
> Today, the following line of JavaScript is safe to include in an inline 
> script tag:
> 
> var x = "</+script><img onerror=alert(1)>";
> 
> Because that line does not contain "</script>", the string "alert(1)" will be 
> treated as the contents of a string.  However, if that line is included in an 
> inline script inside of a template, the modifications of to the parser above 
> will mean that alert(1) will execute as JavaScript rather than being treated 
> as a string, introducing an XSS vector.

I don't follow. Can you give a full example of how this would be included in a 
template and therefore be executed?


>  
> I hope this clarifies the proposal.
> 
> Notes:
> - Just because it's described this way doesn't mean it has to be implemented 
> this way - implementations could do template parsing in a single pass with 
> HTML parsing if desired. I wrote it this way mainly to demonstrate the 
> desired properties/
> 
> I'm not sure how we'd be able to that without running multiple copies of the 
> tokenizer state machine in parallel.  The tokenizer states for the template 
> fragment parser aren't going to line up in any meaningful way with the 
> top-level tokenizer's search for an appropriate end tag to escape from the 
> script data states.

I'm pretty confident it's *possible* to do a one-pass version of this 
algorithm, but I am not sure if it is easy, or if it is desirable.

What I actually imagined (knowing much less about HTML parsing than you) was 
that you'd enter a different tokenizer state after encountering a <script 
template> than a <script>. But defining that state would be challenging.

Regards,
Maciej


Reply via email to