a future caller alternative ?

# Andrea Giammarchi (12 years ago)

I wonder if there's any discussion about it for ES.next

while callee has always been kinda pointless in my opinion, caller property is not replaceable at all.

Internally, for scope lookup reasons, the caller is always passed somehow, except, I guess, where there's no caller access and the function is optimized thanks to absent outer scope look up.

Why caller? Because there's no other way to understand which method invoked a getter, as the very most basic example.

var obj = Object.defineProperty({}, "caller", {get: function get(){ return get.caller; }});

obj.method = function method() { alert(this.caller === method); };

This opens doors to debuggers (introspection) and APIs magic quite a lot.

2 extra points:

  1. I have not even mentioned arguments, which is not mandatory for caller
  2. I haven't used callee and I don't care about callee

Last, but not least, the more I think about the inability to switch "strict mode" in the wild the more patterns from ES3 injected into ES.next come up in my mind.

Thanks for any sort of response

# Kevin Gadd (12 years ago)

The way caller is a single attribute of the function object arguably makes it useless for authoring reusable code: it breaks in the presence of reentrance, and requires you to keep an accessible reference to every function that might want to know its caller, exposing you to leaks and making closures harder to use in such scenarios.

The problems it's intended to solve are important, but it's a really poor solution to them. I'd love to see caller dead for good and a well engineered solution take its place. -kg (mobile)

# Andrea Giammarchi (12 years ago)

I'd love to see caller dead only after a well engineered solution take its place and is widely adopted, which is the reason I've asked about this future solution I've never seen discussed here.

So, the question is: is there any plan to discuss, to put in agenda, to bring, a "caller" alternative to ES.next ?

# Mark S. Miller (12 years ago)

On Fri, Mar 8, 2013 at 1:32 PM, Andrea Giammarchi < andrea.giammarchi at gmail.com> wrote:

I'd love to see caller dead only after a well engineered solution take its place and is widely adopted, which is the reason I've asked about this future solution I've never seen discussed here.

So, the question is: is there any plan to discuss, to put in agenda, to bring, a "caller" alternative to ES.next ?

There are several JSON RPC debugging APIs for remote debugging of JS processes. There is even some convergence among them. I have not followed these developments for a good long while, but when I did it seemed ripe for codification into a standard. I think this would be a wonderful thing to see, and could lead to platform independent portable debuggers for JS, much as Java Platform Debugger Architecture (JPDA) has done for Java. I do not think this should be part of ES.next in the sense of being incorporated into a future version of Ecma 262. Rather, I think it should be on a separate tc39 track, in the same sense that the i18n effort is.

Outside of a debugging API, access to the live stack is a security hole, much as is access to the state encapsulated in a closure. As for access to data representing a dead snapshot of a stack, there's < strawman:error_stack>, which is a

good start. As that page notes, we should still be concerned about the information leak, but we can handle that well by hiding the access in a WeakMap. See the API at < code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/ses/debug.js

# Andrea Giammarchi (12 years ago)

Thanks Mark, my point is that "use strict" deprecated things without providing alternatives.

monocle mustache instead of with is nice to have (unfortunately it breaks now)

..args instead of arguments is cool too

callee ain't needed since named function expression exists

caller ? As I've said the introspection is just one cool aspect of caller, new APIs compatible with "use strict" could be something awesome for developers too.

Thanks to its dynamic nature, is quite easy to wrap all global functions and all objects functions with wrappers that store the latest invoked callback somewhere for a global caller but this is a monster against quite elegant solution caller has been for long time (and I've never had those problems, I've always addressed caller once, when needed, at the top of the function and never accessed again so never a problem, IMO)

If this decision could be made with tc39 that's already something ... is the silence I hear around caller that worries me :-)

# Kevin Gadd (12 years ago)

The Error.stack strawman is a great start at making Error.stack's contents machine-readable, but doesn't remotely approach being a solution for use cases previously addressed by Function.caller.

I don't really understand the security argument in this case. Being able to identify the particular function at offset N in the stack shouldn't expose any privileged information, unless you're somehow assuming that this would expose locals or closed-over values... it's not my understanding that this was the case originally with caller and I don't know off hand of any use cases that would address other than debugger use cases (Which, as you mention, are best addressed by a debugging API). If anything, being able to cheaply and reliably walk the stack to - for example - identify your caller would allow you to implement some interesting security patterns in your own code, if for some reason you were trying to do sandboxing and code access security in pure JS. If specified correctly you could make it possible to walk the stack and ensure that the information you're getting isn't being spoofed, which would allow you to reliably limit callers of a given 'protected' function to a fixed whitelist of trusted functions, something you can't do by parsing a dead stack trace.

Error.stack is also a terrible choice for any scenario where you want adequate performance. I don't expect stackwalking to ever be fast, but there's a huge difference between 'give me the identity of my caller' and 'turn the entire call stack into a string, and also, construct an exception instance since that's how I'm getting the stack'.

I agree with Andrea that the loss of caller in strict mode was painful and it would be troublesome if that feature set is gone forever. It's one of the reasons I periodically consider ceasing to generate strict-mode code in my compiler.

A key point I want to make here: Debugging is not the only reason people will want to walk the stack. It is possibly the best and most common reason, but in the wild I regularly encounter applications that use limited forms of stack-walking for other purposes: Code access security, metaprogramming, logging, etc. These are all reasonable use cases, and in particular I think code access security and detailed logging are both use cases that one could argue should deliver reasonable performance as well, unless your goal is to instead handle those use cases entirely with special features baked into the language or libraries.

Apologies if I've missed some huge design philosophy underpinning the design of ES6/ES7 re: security/sandboxing; I also don't really know/understand how Caja fits into the picture.

# Kevin Reid (12 years ago)

On Fri, Mar 8, 2013 at 2:13 PM, Kevin Gadd <kevin.gadd at gmail.com> wrote:

The Error.stack strawman is a great start at making Error.stack's contents machine-readable, but doesn't remotely approach being a solution for use cases previously addressed by Function.caller.

I don't really understand the security argument in this case. Being able to identify the particular function at offset N in the stack shouldn't expose any privileged information

The problem is exposing the ability to invoke the function. Not 'privileged' information, but 'privileged' operations.

If anything, being able to cheaply and reliably walk the stack to - for example - identify your caller would allow you to implement some interesting security patterns in your own code, if for some reason you were trying to do sandboxing and code access security in pure JS. If specified correctly you could make it possible to walk the stack and ensure that the information you're getting isn't being spoofed, which would allow you to reliably limit callers of a given 'protected' function to a fixed whitelist of trusted functions, something you can't do by parsing a dead stack trace.

Java tried stack inspection. It has failed. It has been responsible for quite a few vulnerabilities (of the sort which allow Java applets to break their sandbox) and does not compose well.

Apologies if I've missed some huge design philosophy underpinning the design of ES6/ES7 re: security/sandboxing; I also don't really know/understand how Caja fits into the picture.

References constitute permissions. To have a reference to a function is to be able to invoke it is to have the permission.

# Kevin Gadd (12 years ago)

Is this 'references constitute permissions' design philosophy written up on the wiki somewhere so I can understand the motivations behind it? It feels a dramatic divergence from the origin-based security model, and it's complex enough in practice that I assume I won't be able to participate in any discussion involving security unless I thoroughly understand your motivations in advocating this model and using it to justify the removal of features.

Re: stack inspection, I'm aware of it being used in scenarios other than Java. Is there some conclusive proof out there that stack inspection is fundamentally unworkable, or is it merely just intrinsically flawed as exposed in Java? I would not leap from the latter to the former, but I'm also not a CS researcher. My goal here was merely to list out real world use cases for stack walking that I have encountered in real applications, some of which can't be easily implemented without it.

# Andrea Giammarchi (12 years ago)

So the point is that a function dealing with unknown objects can be reached and invoked and my getter is an excellent example for this kind of "attack" but again, why ES5 went through the Object.seal/freeze/preventExtension direction for Objects but just dropped functionalities instead of going through Function#secure() approach where "use strict" or not, which is easy to drop via Ajax calls too, together with minifiers, linters, or transpilers, that function would never carry the .caller and its arguments won't expose the callee ?

Wouldn't this direction solve in a better way everything and keep giving developers the ability to use callers for all others non debugger related tasks?

I would let developers decide, as it is for Object.freeze() approach, and explain where functions should not be reachable instead of "freezing all functions by default" under use strict directive.

# Brandon Benvie (12 years ago)

As an example of the security vulnerabilities possibly exposed by being able able to get the caller, look to V8's somewhat recently fixed toString/valueOf caller that exposed the internal operator functions like MUL, DIV, etc. Unpatchable (by something like Caja) communication channels, capability leaks abound. bbenvie.com/articles/2012-08-29/Interview-With-the-All-Stars-From-V8-s-runtime-js-

# Andrea Giammarchi (12 years ago)

OK but if it's about being able to break an environment caller would be at the end of a list of problems :-/

# Mark S. Miller (12 years ago)

On Fri, Mar 8, 2013 at 2:38 PM, Kevin Gadd <kevin.gadd at gmail.com> wrote:

Is this 'references constitute permissions' design philosophy written up on the wiki somewhere so I can understand the motivations behind it?

Apologies for multiple instances of self-citation below.

Not on the EcmaScript wiki, except by reference to "object-capability" or "ocap". Other wikis with good material: < en.wikipedia.org/wiki/Object-capability_model> and <

wiki.erights.org/wiki/Main_Page>. Many people have said that my <

erights.org/talks/thesis/markm-thesis.pdf> and <

srl.cs.jhu.edu/pubs/SRL2003-02.pdf> are good starting points.

For the application of these ideas to JavaScript, I am also partial to the talks I gave at VUB: www.youtube.com/watch?v=w9hHHvhZ_HY and <

www.youtube.com/watch?v=oBqeDYETXME>. These are part one and part

two of an extended talk but had to be accessible to people who could only attend one. If you watch both, you can skip something like the first 10 minutes of the second one.

For introductions, another favorite of mine is Marc Stiegler's < www.youtube.com/watch?v=eL5o4PFuxTY> "The Lazy Programmer's Guide to

Secure Computing".

There is much much else on this topic, but these are good places to start. Others no doubt have other favorite papers, pages, or presentations. Without overwhelming the list, it would be good to see some of these posted.

It feels a dramatic divergence from the origin-based security model,

Indeed! Origin-based security has been a nightmare.

and it's complex enough in practice that I assume I won't be able to participate in any discussion involving security unless I thoroughly understand your motivations in advocating this model and using it to justify the removal of features.

I certainly agree that you should learn this model. I hope that once you do you'll agree that it's actually much simpler and much more expressive than the security you're used to.

Re: stack inspection, I'm aware of it being used in scenarios other than Java. Is there some conclusive proof out there that stack inspection is fundamentally unworkable, or is it merely just intrinsically flawed as exposed in Java? I would not leap from the latter to the former, but I'm also not a CS researcher. My goal here was merely to list out real world use cases for stack walking that I have encountered in real applications, some of which can't be easily implemented without it.

My favorite explanation is Tyler's < www.hpl.hp.com/techreports/2009/HPL-2009-20.pdf>. See Fred

Spiessen's www.evoluware.eu/fsp_thesis.pdf for a more formal and

somewhat different treatment.

# Mark S. Miller (12 years ago)

Adrian Mettler's thesis < www.eecs.berkeley.edu/Pubs/TechRpts/2012/EECS-2012-244.html> is

about Joe-E, which brings ocaps to Java is a very similar way to how we bring ocaps to JS. The Joe-E project is at code.google.com/p/joe-e.

The really important thing about Adrian's thesis is it clearly articulates a new goal that has been implicit in much previous ocap work but not previously explained: "reviewable security".

# Andrea Giammarchi (12 years ago)

Mark, that is an exhaustive list of links and talks but how many real use cases where we let the user inject any sort of script code in the website and we inject malicious libraries we are not aware, compared with the number of all website that would never suffer any problem with this ?

Comparing Java Applets with JavaScript is a no-go, Java had privileged access to the system, nothing caller could achieve in all it's possible evil forms, neither eval could do much there.

I think there are no real use cases where caller is dangerous if not few academic purpose attempts to make it safer, and you seemed to work in probably all of them ... ask devs out there how many are using those libraries.

As summary, you ask us to bring real cases where caller is needed, I would do the other way around: bring real cases in the real world where caller could be such disaster because trusting user inputs and blindly include external libraries are not, again, real world use cases ... not the majority of them, am I wrong ?

I see this like "don't use SQKL ever because there could be SQL injections" ... sense? None for me :-/

# Jorge Chamorro (12 years ago)

On 09/03/2013, at 00:54, Andrea Giammarchi wrote:

Mark, that is an exhaustive list of links and talks but how many real use cases where we let the user inject any sort of script code in the website and we inject malicious libraries we are not aware, compared with the number of all website that would never suffer any problem with this ?

Comparing Java Applets with JavaScript is a no-go, Java had privileged access to the system, nothing caller could achieve in all it's possible evil forms, neither eval could do much there.

I think there are no real use cases where caller is dangerous if not few academic purpose attempts to make it safer, and you seemed to work in probably all of them ... ask devs out there how many are using those libraries.

As summary, you ask us to bring real cases where caller is needed, I would do the other way around: bring real cases in the real world where caller could be such disaster because trusting user inputs and blindly include external libraries are not, again, real world use cases ... not the majority of them, am I wrong ?

I see this like "don't use SQKL ever because there could be SQL injections" ... sense? None for me :-/

I think the key terms are "cooperation under mutual suspicion", "mashups", and "object capability": the idea is that you'd want to be able to run untrusted possibly evil code side by side with your code in your page (e.g. an ad and a payment gateway).

Other links:

Gears and the Mashup Problem: www.youtube.com/watch?v=qfBL2sc2zUU

Web Forward: www.youtube.com/watch?v=yh7TeoEwNyI#t=15m40s

Securing JavaScript: www.youtube.com/watch?v=T6TTQoqln7c

We'd much rather play with unloaded guns than in hopes that nobody else pulls the trigger?

# Andrea Giammarchi (12 years ago)

but then again, the list of problems is massive here if it's about trustiness. Object.prototype can be enriched or some method changed, parseInt and parseFloat can be redefined to change payment details and stuff, String.prototype.trim can be faked to read all written fields before these are sent if the app does the cleanup, Function.prototype.apply/call can be redefined too so access to "unknown functions" is granted again ... and all we worry about is a caller able to access without changing a thing a possibly unknown and private scope that if executed all it could do is causing an error?

I am sorry but this looks/sounds/feels like an academic exercise without concrete and reasonable facts on where this can be a problem. Drop call and apply too then or think about putting back the powerful caller please, thanks.

Here how any function can be trapped somewhere else, invoked, and analyzed, during an app lifecycle.

'use strict'; (function(FunctionPrototype){ function analyze(callback, method, args) { alert([ callback, method, cBound([].slice, args) ].join("\n")); return aBound(callback, args); } function call() { return analyze(this, 'call', arguments); } function apply() { return analyze(this, 'apply', arguments); } var $call = FunctionPrototype.call, cString = "" + $call, cBound = $call.bind($call), $apply = FunctionPrototype.apply, aString = "" + $apply, aBound = $apply.bind($call) ; call.toString = function toString() { return cString; }; apply.toString = function toString() { return aString; }; FunctionPrototype.call = call; FunctionPrototype.apply = apply; }(Function.prototype));

// test (function(){ var pvt = {}; function test(a, b) { return this.sum = a + b; } alert(test.call(pvt, 1, 2)); // 3 alert(pvt.sum); // 3 }());

Best

# David Bruant (12 years ago)

Le 08/03/2013 22:19, Andrea Giammarchi a écrit :

This opens doors to debuggers (introspection) and APIs magic quite a lot.

If you want to write a debugger, use a debugger API [1] which is only executed in privileged environments, no?

Debuggers are useful, but pierce encapsulation which is useful for program integrity. I don't think making a debugger API available to all programs is a good idea.

David

[1] developer.mozilla.org/en-US/docs/SpiderMonkey/JS_Debugger_API_Guide

# Andrea Giammarchi (12 years ago)

I do NOT want to write a debugger and yet I need caller, can you imagine ?

Andrea

# Kevin Gadd (12 years ago)

I really don't understand why the debugger thing is being trotted out again. It was addressed at the beginning of the thread: There are lots of real world applications that use debugger-style introspection (in particular, stack walking) for purposes that are not debugging.

Now, to be fair, that may not justify exposing any of those features if the security threat posed by having introspection is so incredibly dire. But 'just use a debugger API' isn't really a solution for any of these applications. Debugger APIs are heavyweight and usually have tremendous performance consequences, preventing their use for solving Application Problems. In reality, the answer will have to be 'you can't do that in JavaScript', which probably isn't the end of the world since that's the current answer to anything that needs weak references.

# Brendan Eich (12 years ago)

Mark S. Miller wrote:

It feels a dramatic divergence from the origin-based security
model,

Indeed! Origin-based security has been a nightmare.

Any access control system with hand-coded access monitoring in a big C++ codebase will be.

In SpiderMonkey + Gecko in Firefox, and probably in other browsers, we actually use OCap under the hood and have for years. In HTML5, the WindowProxy/Window distinction was finally specified, as an ad-hoc instance of OCap membranes.

Any time we deviate from OCap, we regret it for both security bug and access-checking overhead reasons.

# Mark S. Miller (12 years ago)

On Sat, Mar 9, 2013 at 4:56 PM, Kevin Gadd <kevin.gadd at gmail.com> wrote:

I really don't understand why the debugger thing is being trotted out again. It was addressed at the beginning of the thread: There are lots of real world applications that use debugger-style introspection (in particular, stack walking) for purposes that are not debugging.

Now, to be fair, that may not justify exposing any of those features if the security threat posed by having introspection is so incredibly dire. But 'just use a debugger API' isn't really a solution for any of these applications. Debugger APIs are heavyweight and usually have tremendous performance consequences, preventing their use for solving Application Problems.

Another way to view the phrase "debugging API" is "properly stratified privileged reflection API". Indeed, the famous Mirrors paper used JPDA as an example of a properly stratified reflection system. The key thing about debugging APIs is they get the privilege separation right -- because they must. A well designed mirror system or mirror-like system could as well. I have discussed this repeatedly with the co-authors of that paper -- Dave Ungar and Gilad Bracha (cc'ed) -- and IIRC they enthusiastically agree. The KeyKOS operating system had an operation for rights-amplifying a "start key" or "resume key" to a "domain key". In our terms, a start key is like a closure reference and a domain key is like a reference to the reified lexical environment captured by that closure, i.e., a mirror on the state of that closure. A resume key is like a continuation, so reflecting on resume keys -- if you have the privileges needed to do so -- enables one to effectively walk back the stack of outstanding IPC requests. The logic by which KeyKOS (and its descendants EROS, CapROS, GuardOS, Coyotos) managed the right-to-reflect could be a good starting point for doing likewise with language-based mirrors.

This would be an excellent research topic for someone to take on. If someone takes it on seriously, I may well be interesting in advising the effort. However, the work of TC39 is not the right place to do this kind of research (unless its crucial to an urgent goal, which this one isn't). Once such research bears fruit, we can then consider whether to take this to TC39 as a proposal for ESx, for some future x.

In reality, the answer will have to be 'you can't do that in JavaScript', which probably isn't the end of the world since that's the current answer to anything that needs weak references.

I expect to propose weak references for ES7. I think I have an adequate answer to the security issues that took this off the table for ES6. More later.

# Bill Frantz (12 years ago)

It should be pointed out that KeyKOS resume keys could, like proper tail-call optimization, eliminate the ability to "walk the stack" to determine the caller. In KeyKOS, the process had direct control over usage of the resume key. It could pass it to an object is was "calling" in place or creating a resume key to itself with a normal call. This loss of ability to walk the stack is much like tail-call optimization of:

function a(args) { ... some calculation return b(otherargs); }

Where the optimization passes the address of a's caller as the return address for b and b can't see a's activation record on the stack.

Cheers - Bill

On 3/9/13 at 6:57 PM, erights at google.com (Mark S. Miller) wrote:

Another way to view the phrase "debugging API" is "properly stratified privileged reflection API". Indeed, the famous Mirrors paper used JPDA as an example of a properly stratified reflection system. The key thing about debugging APIs is they get the privilege separation right -- because they must. A well designed mirror system or mirror-like system could as well. I have discussed this repeatedly with the co-authors of that paper -- Dave Ungar and Gilad Bracha (cc'ed) -- and IIRC they enthusiastically agree. The KeyKOS operating system had an operation for rights-amplifying a "start key" or "resume key" to a "domain key". In our terms, a start key is like a closure reference and a domain key is like a reference to the reified lexical environment captured by that closure, i.e., a mirror on the state of that closure. A resume key is like a continuation, so reflecting on resume keys -- if you have the privileges needed to do so -- enables one to effectively walk back the stack of outstanding IPC requests. The logic by which KeyKOS (and its descendants EROS, CapROS, GuardOS, Coyotos) managed the right-to-reflect could be a good starting point for doing likewise with language-based mirrors.


Bill Frantz | Concurrency is hard. 12 out | Periwinkle (408)356-8506 | 10 programmers get it wrong. | 16345 Englewood Ave www.pwpconsult.com | - Jeff Frantz | Los Gatos, CA 95032

# Kevin Reid (12 years ago)

On Sat, Mar 9, 2013 at 10:13 AM, Andrea Giammarchi < andrea.giammarchi at gmail.com> wrote:

but then again, the list of problems is massive here if it's about trustiness. Object.prototype can be enriched or some method changed, parseInt and parseFloat can be redefined to change payment details and stuff, String.prototype.trim can be faked to read all written fields before these are sent if the app does the cleanup, Function.prototype.apply/call can be redefined too so access to "unknown functions" is granted again

Yes, taking care of all those things is necessary as well. ES5 provides us the tools to do so: Object.freeze(). If you recursively freeze all standard global objects then all of the issues you mention are handled. Secure ECMAScript (SES), developed by Mark Miller, does this; it provides an execution environment which is secure (given a sufficiently conformant ES5 implementation).

... and all we worry about is a caller able to access without changing a thing a possibly unknown and private scope that if executed all it could do is causing an error?

If by “cause an error” you mean throw an exception, that's not all it can do. Here's a very simplified example, which I have tried to make only moderately silly; imagine a calculator/spreadsheet web-app with user-defined functions. In order to make security relevant, imagine that it (a) has persistent user data (i.e. a script could modify it on the server by XHR), and (b) allows sharing of prepared calculations with other people.

var input = document.getElementById('input'); var output = document.getElementById('output'); function execute(fun, filter) { output.innerHTML = filter(fun(input.value)); } function basicFilter(value) { return (+value).toFixed(4); }

execute(new Function("x", "return (+x) + 1"), basicFilter);

SES patches the Function constructor so that it cannot access the normal global scope (e.g. document itself), so the string code here can only perform computation and use safe constructors (e.g. Object, Array, Date).

However, if the "user-written" function could use .caller, then it could invoke the caller (which is the execute() function) with an alternate 'filter' which returns arbitrary HTML, at which point it can take over the page and therefore the user's session as well.

In summary: • Defending code from other code is not just a theoretical possibility: SES is a working implementation. • Not prohibiting .caller is sufficient to defeat this defense.

# Brandon Benvie (12 years ago)

On 3/11/2013 12:41 PM, Kevin Reid wrote:

On Sat, Mar 9, 2013 at 10:13 AM, Andrea Giammarchi <andrea.giammarchi at gmail.com <mailto:andrea.giammarchi at gmail.com>> wrote:

Yes, taking care of all those things is necessary as well. ES5 provides us the tools to do so: Object.freeze(). If you recursively freeze all standard global objects then all of the issues you mention are handled. Secure ECMAScript (SES), developed by Mark Miller, does this; it provides an execution environment which is secure (given a sufficiently conformant ES5 implementation).

I would note, however, that it looks like at, least in browsers, freezing the window or even any single property on it will no longer be an option in the future. I believe the technique used by SES (correct me if I'm wrong) is using is more complex than simply freezing the window (though I believe it does freeze every property recursively from there). Something like shadowing all whitelisted global names and preventing any kind of direct access to the window object at all. This requires some amount of source code sandboxing to accomplish.

# Kevin Reid (12 years ago)

On Mon, Mar 11, 2013 at 12:56 PM, Brandon Benvie <bbenvie at mozilla.com>wrote:

On 3/11/2013 12:41 PM, Kevin Reid wrote:

Yes, taking care of all those things is necessary as well. ES5 provides us the tools to do so: Object.freeze(). If you recursively freeze all standard global objects then all of the issues you mention are handled. Secure ECMAScript (SES), developed by Mark Miller, does this; it provides an execution environment which is secure (given a sufficiently conformant ES5 implementation).

I would note, however, that it looks like at, least in browsers, freezing the window or even any single property on it will no longer be an option in the future. I believe the technique used by SES (correct me if I'm wrong) is using is more complex than simply freezing the window (though I believe it does freeze every property recursively from there).

Right. We construct an object which has the bindings specified by ES5 (Object, Array, parseInt, ...), but not the DOM (document, window, HTMLElement...). Actual access to the DOM by untrusted code is done with intermediation and is not part of SES per se. Trying to turn window itself into a sandbox is a non-starter.

Something like shadowing all whitelisted global names and preventing any kind of direct access to the window object at all. This requires some amount of source code sandboxing to accomplish.

The minimal solution is to (conservatively) find all (potential) free variables in the source code and bind them, which we currently do using an outer 'with' statement (in order to be able to intercept accesses using accessor properties, for best emulation of legacy global-variable semantics).

# Andrea Giammarchi (12 years ago)

the outer with statement ... you see my point? we are dropping powerful features in order to make JavaScript the toy we all think is since ever, isn't it .... fear driven features, SES I've never personally used, things that any other general purpose language will leave/consider and then eventually tell developers how to or how to not use them as linter has done until now.

Once JS will be not flexible, not dynamic, not powerful and with introspection possibilities, not JS anymore, I think we can also chose a new name for the language.

Bear in mind, AFAIK I am the first one that suggested to freeze the global: webreflection.blogspot.de/2012/08/a-safer-js-environment.html

and it was discussed here too but again, if I know what my code is doing, why you or your SES should be able to not let me do things the way I'd like to.

As summary: the reason for dropping caller is privileged access but apply, bind, and call have same weakness/privilege/power ... why are these allowed?

Why cannot be caller back (humans can be wrong and hopefully fix, right?) and update specs so that Object.freeze(callback) or any other meaningful method will cause that behavior when meant/needed ?

Minifiers, most of them, drop 'use strict' so 90% of code is still not strict in production so I believe is not too late.

Best

# Dean Landolt (12 years ago)

On Mon, Mar 11, 2013 at 5:51 PM, Andrea Giammarchi < andrea.giammarchi at gmail.com> wrote:

the outer with statement ... you see my point? we are dropping powerful features in order to make JavaScript the toy we all think is since ever, isn't it .... fear driven features, SES I've never personally used, things that any other general purpose language will leave/consider and then eventually tell developers how to or how to not use them as linter has done until now.

I can barely grok any of this but it smells unnecessarily trollish :-/

Once JS will be not flexible, not dynamic, not powerful and with introspection possibilities, not JS anymore, I think we can also chose a new name for the language.

With all of the introspective goodness coming in es6 and es7 this statement is ludicrous.

Bear in mind, AFAIK I am the first one that suggested to freeze the global: webreflection.blogspot.de/2012/08/a-safer-js-environment.html

and it was discussed here too but again, if I know what my code is doing, why you or your SES should be able to not let me do things the way I'd like to.

As summary: the reason for dropping caller is privileged access but apply, bind, and call have same weakness/privilege/power ... why are these allowed?

This statement suggests you don't understand the arguments against caller. It should be obvious that it's not the same thing as apply, bind, or call -- in each of the latter forms you're explicitly handing out the this reference capability. There's clearly no capability leak as with caller.

# Andrea Giammarchi (12 years ago)

I've asked if there is anything discussed able to replace caller, this is the topic, and nothing came out.

Now you are saying that ES6 and ES7 has same power, but before you or somebody else said that's not the case.

The this reference has not mentioned at all as a "main problem" so I might misunderstand your statement.

At the end of the day there is no answer here but of course that would be me not understanding it ... that's easy

# Andrea Giammarchi (12 years ago)

On Mon, Mar 11, 2013 at 3:39 PM, Dean Landolt <dean at deanlandolt.com> wrote:

it's not the same thing as apply, bind, or call -- in each of the latter forms you're explicitly handing out the this reference capability. There's clearly no capability leak as with caller.

I wonder how would you access the this reference using caller from somewhere else, exactly, 'cause more I think about above sentence, the more I realize I really do not understand what are you talking about ...

(function test() { function what() { alert(what.caller); } what(); }());

So I've got test there, now what about leaking this ... how ?

# Dean Landolt (12 years ago)

On Mon, Mar 11, 2013 at 7:57 PM, Andrea Giammarchi < andrea.giammarchi at gmail.com> wrote:

On Mon, Mar 11, 2013 at 3:39 PM, Dean Landolt <dean at deanlandolt.com>wrote:

it's not the same thing as apply, bind, or call -- in each of the latter forms you're explicitly handing out the this reference capability. There's clearly no capability leak as with caller.

I wonder how would you access the this reference using caller from somewhere else, exactly, 'cause more I think about above sentence, the more I realize I really do not understand what are you talking about ...

(function test() { function what() { alert(what.caller); } what(); }());

So I've got test there, now what about leaking this ... how ?

The leakage is that caller is a reference -- having that reference gives you the *capability *to follow any further references on its object graph. This reference wasn't explicitly handed out (as is always the case with this-binding in call, apply and bind) -- it was just leaked out by the simple fact that the function was called. It's very possible the caller has all kinds of powers you didn't intend to expose to the callee -- these powers have been leaked. It's really not complex -- this is an inherent, unpluggable leak. And since OCap is now the security model of es, there really no sense in trying to revive caller -- it's gone for good.

# Andrea Giammarchi (12 years ago)

if I do not return that function explicitly and since I own that function being the one that put a caller inside it where is exactly the problem ... once again?

I would agree 100% if there was a global way to retrieve the currently invoked function but caller, is even more secure than call, apply, and bind, 'cause it cannot be overwritten in a meaningful way ( ok, it could probably deleting the descriptor and putting it back later on )

If I've passed that object I could also argue that object should not be modified until I decide. There's no mechanism to drop a temporarily frozen state because I've sent the object I trust to another function.

Moreover, if I created the function that uses .caller is because I own that function and I put it publicly accessible and maybe I want to know who's invoking it and how ... is like baking a pie asking you to let me know when you want to eat it because you know what ? maybe I can throw if the action is eat() instead of throw() when the context expiration date is expired, you know what I mean? I've created that bloody pie, who better than me can decide or suggest when and how to use it?

If you call unknown functions inside your code, the fact there is a caller is actually the last problem you might have, isn't it?

Also, if that is the real problem, you can maybe just Function('m','return m()')(method) so that caller would be null, right ?

But I understand there's no way caller is gonna be back, even if reasons aren't in my opinion, valid enough.

br

# Andrea Giammarchi (12 years ago)

OK, this won't work Function('m','return m()')(method) ... but I wondr if the key is there, in anonymous functions, that could be specced being anonymous, won't be leak caller and arguments or anything ... no idea, but I think the solution could be different, imho.

# Andrea Giammarchi (12 years ago)

apparently only Chrome fails here addressing the caller in advance ... Safari and Firefox get this right:

function withoutACaller(method, context, args) { var window = Function('return this')(), documentElement = document.documentElement, script = document.createElement('script'), uid = '__withoutACaller' + Math.random(), result; window[uid] = [method, context, args]; script.text = [ 'try{','=','[0].apply(','[1],','[2])}catch(e){','[3]=e}' ].join( "window['" + uid + "']" ); documentElement.insertBefore( script, documentElement.firstChild ); result = window[uid]; delete window[uid]; documentElement.removeChild( script ); if (result instanceof Array && result.length == 4) { throw result[3]; } return result; }

(function TEST(){ alert(withoutACaller(function test(a, b, c) { alert(test.caller); // withoutACaller in Chrome return a + b + c; }, {}, [1, 2, 3])); }());

# Domenic Denicola (12 years ago)

From: Dean Landolt

The leakage is that caller is a reference -- having that reference gives you the capability to follow any further references on its object graph. This reference wasn't explicitly handed out (as is always the case with this-binding in call, apply and bind) -- it was just leaked out by the simple fact that the function was called. It's very possible the caller has all kinds of powers you didn't intend to expose to the callee -- these powers have been leaked. It's really not complex -- this is an inherent, unpluggable leak. And since OCap is now the security model of es, there really no sense in trying to revive caller -- it's gone for good.

As an excellent illustration of this, I was just made aware that the Node.js contextify sandboxing package is vulnerable to just such a "caller attack":

brianmcd/contextify#56

# Domenic Denicola (12 years ago)

From: Andrea Giammarchi

if I do not return that function explicitly and since I own that function being the one that put a caller inside it where is exactly the problem ... once again?

If I've passed that object I could also argue that object should not be modified until I decide. There's no mechanism to drop a temporarily frozen state because I've sent the object I trust to another function.

I've created that bloody pie, who better than me can decide or suggest when and how to use it?

If you call unknown functions inside your code, the fact there is a caller is actually the last problem you might have, isn't it?

In general, Andrea, I think you'd be well-served to read up on the OCAP resources that Mark Miller linked to a few replies ago:

esdiscuss/2013-March/029039

You do seem to be missing some fundamental principles of OCAP, as exemplified by lines like those quoted above. It's really hurting how you're perceived on this list, because you are just forging ahead with your objections and agenda without doing the necessary background reading to understand the setting in which your questions need to be framed. Even if you object to OCAP in principle, you clearly haven't spent much time looking into it, so it's hard to take your objections seriously.

I realize you're probably busy and reading those articles and watching those videos will consume a decent amount of your time, but, well, you're consuming the time of a lot of people on this list. We're all well-intentioned here and are generally happy to spend our time guiding you toward understanding, but there's only so much exposition we can do on such a broad subject. It will be a much more productive dialogue once you ground yourself in the basic concepts underlying ECMAScript's chosen security model, and we can discuss from that foundation.

# Andrea Giammarchi (12 years ago)

I'll read that,

# Mark S. Miller (12 years ago)

I also recommend the talks by Doug Crockford that Jorge Chamorro links to at esdiscuss/2013-March/029072.

They are excellent.

# David Bruant (12 years ago)

Le 11/03/2013 22:51, Andrea Giammarchi a écrit :

the outer with statement ... you see my point? we are dropping powerful features in order to make JavaScript the toy we all think is since ever

A while ago I discussed the 'with' trick on es-discuss (I don't remember when, it was a message about dynamic loaders IIRC) and I think Mark's reply was that it was a "temporary" (ES5 era) hack and the proper ES6 way would be to use a custom loader (using the a custom 'global' property). In that instance, "with" isn't a powerful feature, it's a convenience used so that the relevant sandboxing code is 6 lines instead of a full parser, because if there was no "with", that's probably what Caja would be doing anyway.

# Mark S. Miller (12 years ago)

you remember correctly.