proposed relationships of Secure EcmaScript, ES3.1, and ES4.
Mark S. Miller
erights at google.com
Wed Feb 20 16:27:46 PST 2008
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,
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
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.
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.)
At <http://wiki.ecmascript.org/doku.php?id=es3.1:secure_eval> I see
the intention to include a secure eval() in ES3.1 while (elsewhere)
deprecating the ES3 global eval() function. (Note that, regardless of
what language the secure eval() evals, I disagree with the proposal on
that page to make eval() be a method of strings. But we can argue
about the packaging of sesEval() separately.)
Crock and I met last Monday. Crock began the meeting by writing the
JSON < ADsafe < Cajita < Caja < ES3 < ES4
on the whiteboard. To a first approximation each language is a proper
subset of the languages to its right. However, currently, each of
these subset relationships is broken in various ways. While I don't
think these subset relationships can ever be fully repaired, I believe
they can be made accurate enough for practical purposes. On Monday,
Crock and I made good progress reconciling differences between ADsafe
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.
2) I propose that Cajita be considered a candidate for ses.
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.
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
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.
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.) 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)
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. So...
5) I propose the addition of Function.prototype.newInstance(argList) such that
f.newInstance([a,b]) ==== new f(a,b)
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
More information about the Es4-discuss