Re: E4H and constructing DOMs

On Sat, Mar 9, 2013 at 8:58 AM, Adam Barth <w3c@adambarth.com> wrote:

> (Consolidating replies again.)
>
> On Fri, Mar 8, 2013 at 1:27 PM, Mike Samuel <mikesamuel@gmail.com> wrote:
> > 2013/3/8 Adam Barth <w3c@adambarth.com>:
> >> tl;dr: No one is disputing that string templates as currently designed
> >> are insecure by default and will lead authors to write code filled
> >> with XSS vulnerabilities.  I recommend removing string templates for
> >> the spec until these security issues are resolved.
> >
> > I oppose this on the grounds that it is better than current ad-hoc
> > content creation practices, and can lead to a principled solution in a
> > way that AST approaches cannot.
>
> It's clear that you oppose removing string templates from the
> specification, but you still haven't brought forth any technical
> arguments disputing that that string templates as currently designed
> are insecure by default and will lead authors to write code filled
> with XSS vulnerabilities.
>
> > My argument is that we need to produce minimal language extension
> > points to allow experimentation by security researchers.
>
> I can see what that's appealing to you as a security researcher, but I
> doubt that's the best thing for the vast majority of ECMAScript
> authors.
>
> On Fri, Mar 8, 2013 at 5:53 PM, Jonas Sicking <jonas@sicking.cc> wrote:
> > On Fri, Mar 8, 2013 at 1:15 PM, Adam Barth <w3c@adambarth.com> wrote:
> >> Right, that's why the example in my first email is XSS:
> >>
> >> ---8<---
> >> var firstName = [...];
> >> var lastName = [...];
> >> header.innerHTML = `<h1>Welcome ${ firstName } ${ lastName }!</h1>`;
> >> --->8---
> >
> > It's hard to say if the blame for this is with quasis or with
> > .innerHTML though. I.e. would not having quasis cause people to use
> > your AST based template system, or would they just use string
> > concatenation?
>
> I don't think it's that important to assign blame.  There's plenty of
> evidence that developers are very happy with AST-based solutions when
> done well.  For example, many, many developers use prepared statements
> for SQL and Haml for HTML.
>
> Again, not advocating for E4H, but the following seems to have good
> developer ergonomics:
>
> ---8<---
> var firstName = [...];
> var lastName = [...];
> header.appendChild(@<h1>Welcome { firstName } { lastName }!</h1>);
> --->8---
>
> It also has the advantage of executing faster because we don't need to
> parse every fragment of the template twice.  :)
>
> > I agree that AST solutions have advantages. But the cost of
> > introducing them is really high and as far as I can tell there is no
> > way to create a generic AST-based solution. I.e. if we wanted to do
> > something SQL-like for querying databases we'd have to invent a whole
> > new JS syntax for that too.
>
> That seems like less of a problem to me than giving developers a giant
> security footgun.  If we implement string templates as currently
> designed, we're going to spend the next decade cleaning up the
> security mess.
>
> My goal isn't to convince you to implement a particular alternative to
> string templates.  My goal is to convince you that string templates
> (as currently design) are terrible for security and therefore you
> shouldn't implement them.
>
> On Fri, Mar 8, 2013 at 6:04 PM, Domenic Denicola
> <domenic@domenicdenicola.com> wrote:
> > From: Adam Barth [mailto:w3c@adambarth.com]
> >
> >> Right, that's why the example in my first email is XSS:
> >
> >>     var firstName = [...];
> >>     var lastName = [...];
> >>     header.innerHTML = `<h1>Welcome ${ firstName } ${ lastName }!</h1>`;
> >
> >> Whereas the E4H equivalent would not be:
> >
> >>     var firstName = [...];
> >>     var lastName = [...];
> >>     header.appendChild(@<h1>Welcome { firstName } { lastName }!</h1>);
> >
> >
> > I must be missing something, but from my reading you are not gaining
> anything in the ES4H example over the string templates example, if of
> course you modify the last line to be
> >
> >     header.innerHTML = html`<h1>Welcome ${ firstName } ${ lastName
> }!</h1>`;
> >
> > In particular, as has been explained in this thread a few times, there's
> no reason why browsers can't ship a built-in `html` template handler that
> does the same AST-based DOM parsing on the passed template string that ES4H
> would do on the source string following the @-sign, and subsequently
> returns the `outerHTML` of the resulting DOM element.
>
> Even if browser did include such a quasis handler, that would still
> not be the default handler.  That means string templates would be
> insecure by default and will lead authors to write code filled with
> XSS vulnerabilities.
>
> > Indeed, since string templates don't even need to return strings, you
> could do
> >
> >     header.appendChild(htmlel`<h1>Welcome ${ firstName } ${ lastName
> }!</h1>`);
> >
> > where `htmlel` just returns an HTML element constructed using that same
> algorithm (instead of the `outerHTML` of that element).
> >
> > At this point it seems like you are bikeshedding over `@` vs. `htmlel`
> or `{}` vs. `${}`, which leads me to believe I must be missing your
> argument, especially since you emphasize you're not wedded to ES4H and thus
> presumably not wedded to `@` or `{}`.
>
> I don't care at all about the syntax.  If you want to keep backtick as
> the operator, that's fine.  What's important to me are the following:
>
> 1) The template system parses the trusted template content separately
> from the untrusted input data.  In particular, it should fill the
> untrusted data into the leaves of AST produced by parsing the template
> rather than parsing the untrusted data.
>
> 2) The template system does the above by default.
>
> Specifically, I would be perfectly happy with the following syntax:
>
> header.appendChild(`<h1>Welcome ${ firstName } ${ lastName }!</h1>`);
>
> as long as this "hello, world" template is not XSS.
>

I would imagine that some folks on this list would be resistant to having
the default handler be one that produces a DOM instead of a string. Could
we have a browser-provided html handler that does E4H style parsing and not
have a default handler at all? That way, the simplest code path for
developers is to use the browser-provided handler and they have to go out
of their way to do something else, but we still leave the door open for
other use-cases/handlers (e.g. contextually parsed html).

header.appendChild(`<h1>Welcome ${ firstName } ${ lastName }!</h1>`); //
parse error
header.appendChild(html`<h1>Welcome ${ firstName } ${ lastName }!</h1>`);
// E4H style parsing
header.appendChild(myspecialhtmlparser`<h1>Welcome ${ firstName } ${
lastName }!</h1>`); // template strings as currently proposed

The only thing we lose here I think is an easy way to do multiline strings
in JS.

Also, we don't get the static error checking of of E4H. Although, maybe
browsers could special case the html handler and do static error checking.

Ojan


> Adam
>
>
> On Fri, Mar 8, 2013 at 6:04 PM, Domenic Denicola
> <domenic@domenicdenicola.com> wrote:
> > From: Adam Barth [mailto:w3c@adambarth.com]
> >
> >> Right, that's why the example in my first email is XSS:
> >
> >>     var firstName = [...];
> >>     var lastName = [...];
> >>     header.innerHTML = `<h1>Welcome ${ firstName } ${ lastName }!</h1>`;
> >
> >> Whereas the E4H equivalent would not be:
> >
> >>     var firstName = [...];
> >>     var lastName = [...];
> >>     header.appendChild(@<h1>Welcome { firstName } { lastName }!</h1>);
> >
> >
> > I must be missing something, but from my reading you are not gaining
> anything in the ES4H example over the string templates example, if of
> course you modify the last line to be
> >
> >     header.innerHTML = html`<h1>Welcome ${ firstName } ${ lastName
> }!</h1>`;
> >
> > In particular, as has been explained in this thread a few times, there's
> no reason why browsers can't ship a built-in `html` template handler that
> does the same AST-based DOM parsing on the passed template string that ES4H
> would do on the source string following the @-sign, and subsequently
> returns the `outerHTML` of the resulting DOM element. Indeed, since string
> templates don't even need to return strings, you could do
> >
> >     header.appendChild(htmlel`<h1>Welcome ${ firstName } ${ lastName
> }!</h1>`);
> >
> > where `htmlel` just returns an HTML element constructed using that same
> algorithm (instead of the `outerHTML` of that element).
> >
> > At this point it seems like you are bikeshedding over `@` vs. `htmlel`
> or `{}` vs. `${}`, which leads me to believe I must be missing your
> argument, especially since you emphasize you're not wedded to ES4H and thus
> presumably not wedded to `@` or `{}`.
> >
> > Look forward to hearing what I missed!
>

Received on Saturday, 9 March 2013 22:22:32 UTC