proposed relationships of Secure EcmaScript, ES3.1, and ES4.

Brendan Eich brendan at mozilla.org
Wed Feb 20 19:35:41 PST 2008


There's a lot of implicit context here, some of which may be new to  
es4-discuss readers. Also, not everything here is bound to become an  
Ecma standard, as noted in mail I sent earlier today (3.1 could be a  
TR and should be in the view of some on the TC39 committee). Comments  
inline below, but I wanted to clarify, since es4-discuss has mainly  
been about es4, not Caja*/SES/etc.

On Feb 20, 2008, at 4:27 PM, Mark S. Miller wrote:

> At <http://wiki.ecmascript.org/doku.php?id=ses:ses> Doug Crockford
> explains a rationale for a secure variant of EcmaScript, hereafter
> "ses". I am part of a team working on two such variants, Cajita and
> Caja (Caja is mentioned on Crock's page. Cajita is a small ADsafe-like
> subset of Caja). On the first day of the January EcmaScript meeting,
> Crock gave a presentation <http://javascript.crockford.com/ses.ppt> on
> the goals for an official ses.  By Crock's criteria (which I like),
> Cajita and ADsafe would be candidates, but Caja would not due to its
> lack of minimalism. Caja and Cajita are currently defined by
> <http://groups.google.com/group/google-caja-discuss/web/caja-spec.pdf>

One piece of missing context: the TC39 committee generally seemed to  
agree that developing and judging the winner among candidate "secure  
dialects" was both a multi-year mission and beyond the capabilities  
of TC39. Academics and others not willing or able to join Ecma would  
be needed. We wouldn't be able to judge soundness based only on  
formal methods -- we would need to see fairly broad real-world usage  
and evaluate successes and failures. And so on.

I'm not saying SES is pie in the sky or out of bounds for es4-discuss  
-- far from it. I have hopes for your work, which I said at the last  
face to face was in front-runner position, if that can be said at  
this early stage -- I think it can, based on bird-nearly-in-hand  
simple-minded reasoning -- but I'd like to have other candidates to  
evaluate.

I am saying that es4-discuss readers need to have expectations set  
about development, deployment, judging, and *then* standardization,  
if we are to follow Doug's beauty contest approach (which I like).

> As we discussed it, the general sense was that the creation an ses
> seems like a valuable idea. But on the first day, the process of
> deciding on an ses did not seem to be a natural extension of the work
> of the EcmaScript committee. Perhaps this would be a topic for a
> different committee on another day.

I said something stronger: it's not the proper job for a committee in  
the closed-room, pay-to-play sense, to decide. Parliament hath not  
the competence, to borrow from Robert Bolt's play. I suggested a  
prize system with mechanized tests and proofs or other ways of  
objective judging, plus white/gray hat open-source hack attacks over  
a period of time. Just the thought of reps from Adobe, Apple, Google,  
Microsoft, Mozilla, Opera, Yahoo! and other fine organizations  
meeting to decide the winner leaves me cold.

> Due to a suggestion of Kris Zyp, the ses discussion revived on the
> second day. Kris' suggestion (Kris - please correct any inaccuracies)
> is that ES4 include an sesEval operation (name tbd) that would
> evaluate its first argument as an ses program in a lexical scope
> provided by its second argument. The rules of ses would be chosen so
> that a containing page running ES4 could safely sesEval a script from
> an untrusted third party, safe in the knowledge that the only effect
> this sesScript could have on the containing page is according to the
> objects that the containing page explicitly provides to the script.
> (The only entry points into those ES4 objects accessible from ses
> would be according to some whitelisting mechanism, such as Caja and
> Cajita currently implement.)

We have experience in Mozilla with GreaseMonkey's injection of  
privileged methods into "secure eval" sandboxes. Frankly, it has been  
a trail of tears. The hazards are many and hard to see if the outer  
language has things like .call/.apply per ES3, extensions such as  
getters and setters, etc. A whitelist is obviously better than a  
blacklist, but I'm concerned that there are so many hazards, so hard  
to see, that you are creating what I called at the meeting a honey- 
pot for unwary programmers.

In that light, Geoff Garen of Apple suggested the method should be  
called "unsafeEval" -- and I agreed!

> 1) To the degree that we can accommodate it within our other design
> goals, I propose that ES3.1 evolve to replace ES3 in this inequality,
> so as to help repair this inequality. I am certainly willing to evolve
> Caja and Cajita in coordination with any such effort.

That's great to hear.

> 2) I propose that Cajita be considered a candidate for ses.

By whom? We need a better way to judge, not merely good judges; we  
need other candidates. There should be no near-term Ecma stamp of  
approval that we rush to apply to some candidate, if I'm right about  
the need for other people and extensive testing, including deployment.

> 3) I propose that ES3.1 and therefore ES4 include an sesEval() (name
> tbd) that evaluates its first argument as an ses program in a lexical
> scope provided by its second argument.

We've been over this before, and not first in the es3.1: wiki -- the  
original page is

http://wiki.ecmascript.org/doku.php?id=proposals:resurrected_eval
http://wiki.ecmascript.org/doku.php?id=discussion:resurrected_eval

I agree with the comments under "Resolved issues".

Now we could say something about the outer language and the kinds of  
objects that could be injected. But now the secure dialect in the  
sandbox is spreading its reference monitor or capability system into  
the outer language, and that outer language can't be ES3, therefore  
it can't be ES4-in-full (which is a superset of ES3, modulo de-facto  
standards fixes).

> 4) To facilitate the safe interaction between ses objects and ES3.1/ 
> ES4 objects:
>
> 4a) I notice that ES4 already has a notion of a "strict mode" flag. I
> propose that both ES3.1 and ES4 have behavior conditioned on a "strict
> mode" flag.

We've talked about this on this list and in the wiki a bit. The  
current design does not impose runtime changes due to strict mode,  
except to eval -- so there's an exception, and it may be that we can  
tolerate a few more exceptional runtime semantic changes. But we're  
on a slippery slope to two languages, where programs tested under one  
mode fail under the other and interoperation suffers because  
different parties do not use the same modes when testing.

I don't want to make this sound like the end of the world -- indeed,  
it could be the right thing. But again, it seems like something to  
consider, and it may be missing context (for some reading this, if  
not for you and me ;-).

Our thought with ES4 has been: If strict mode (modulo eval) is merely  
a checker that performs type, name, and other lint-like analyses and  
stops certain programs that would run in standard mode from reaching  
runtime, but otherwise does not impose runtime semantic changes, then  
we probably have fewer interop bugs in the field over the next decade  
or two.

> 4b) At <http://bugs.ecmascript.org/ticket/276#comment:11> I propose
> that, in strict mode, if a function is called as a function (as
> opposed to calling it as a method, constructor, or reflectively), then
> its "this" is bound to undefined. In the absence of strict mode,
> "this" should be bound to the global object for ES3 compatibility.

Sliding down-slope another little bit.

> 4c) At the EcmaScript meeting, I proposed that a function called by
> call, apply, or bind should have "this" bound to the first argument of
> that call, bind, or apply -- no matter what value that is. In ES3, if
> the first argument of call or apply is null or undefined, the
> function's "this" is bound to the global object. (If I recall
> correctly, there was general agreement with this proposal by itself.
> If I'm remembering this inaccurately, please correct me.)

The minutes and trac should tell the truth, but I remember general  
agreement on the global substitution for null and undefined being  
considered a design flaw in ES3, which introduced call and apply.

> Although we
> could also make this difference of behavior conditional on strict
> mode, I propose that it be unconditional.
>
> Under these proposals,
>
>     f.apply(undefined, [a,b]) ==== f(a,b) ==== f.call(undefined, a,b)

True in ES3, so would be good to keep true in any strict mode,  
whatever runtime semantic changes it selects from standard mode.

> so we have the ability to reflectively call functions either as
> functions (as above) or as methods. This reflective ability would be
> present in ses as well. However, considering Cajita as a candidate ses
> reveals a functionality hole: Because Cajita contains "new" but does
> not allow manipulation of the prototype chain, Cajita has no ability
> to reflectively call constructors.

This too has been a topic on list and in wiki (and in Narcissus and  
probably other JS-hosted JS implementations). See

http://www.google.com/search?hl=en&hs=e0L&q=site%3Amail.mozilla.org 
+newApply

> So...
>
> 5) I propose the addition of Function.prototype.newInstance 
> (argList) such that
>
>     f.newInstance([a,b]) ==== new f(a,b)

The proposal I like is ... as a unary prefix "splat" operator that  
mimics ...'s usage in rest parameters:

   function f(...rest) { return new g(...rest); }

The expression after the splat operator would have to evaluate to an  
arguments or array object, call it A; this actual parameter would  
have to be last, and it would then supply A.length actuals to the  
called function starting with A[0] up to A[A.length-1]. (... is * in  
Python for positional parameters).

This has been discussed on-list and if it makes it into ES4, it would  
be suboptimal to have f.newInstance too. But I have a bigger concern,  
below.

> 5a) I separately propose that new f(a,b) be considered sugar for
> f.newInstance([a,b]), so that f can override newInstance to
> distinguish being invoked as a constructor from being invoked by other
> means.

This is a nice idea in the abstract, and any middle-aged language  
that doesn't already follow the Zen of Python's "There should be  
one-- and preferably only one --obvious way to do it" line could  
perhaps afford to be expansive, and support both ... as splat and  
newInstance.

However, desugaring new into a call to a metaprogramming function  
without further security mechanism scares me. Right now a host- 
provided function object can insist that it must be invoked only via  
operator new, and it can make its standard name binding(s) have the  
DontDelete and ReadOnly attributes. This is important for integrity  
in Firefox and other Gecko-based browsers for certain objects. Such  
an object may have been around for years, during which it allowed ad- 
hoc ("expando") properties to be set on it, without the value of any  
such property affecting its constructor-only policy, or what code  
runs when it is invoked via operator new. For backward compatibility  
it may be important to continue to support such ad-hoc property setting.

Now add newInstance to Function.prototype. Do the high-integrity  
constructors delegate to this method when invoked via new? You could  
say that such host-provided objects need a host-provided prioritized  
constructor protocol, and newInstance would not be consulted by it.  
Ok, that might be sufficient. It seems necessary. Not saying  
something like this seems like a bad idea. But now you are talking  
about more than just a way to compose operator new with apply.

I like the splat proposal because it's orthogonal to constructor and  
invocation protocols. It cleanly composes apply and new, as well as  
generalizing apply into a special form (unary prefix operator that  
can be used only in a trailing argument expression) which can be used  
with any callable or constructible object.

/be



More information about the Es4-discuss mailing list