All About E: A Language That Infiltrated JavaScript
thenewstack.io
thenewstack.io
Capability Myths Demolished (2003) - https://news.ycombinator.com/item?id=22753464 - April 2020 (30 comments)
E Programming Language - https://news.ycombinator.com/item?id=19981720 - May 2019 (53 comments)
Satan Comes to Dinner (1997) - https://news.ycombinator.com/item?id=16512555 - March 2018 (14 comments)
Concurrency Among Strangers: Programming in E as Plan Coordination (2005) [pdf] - https://news.ycombinator.com/item?id=13653503 - Feb 2017 (2 comments)
Vats – Monte documentation - https://news.ycombinator.com/item?id=13295071 - Jan 2017 (1 comment)
E Programming Language: Write Secure Distributed Software - https://news.ycombinator.com/item?id=11608985 - May 2016 (21 comments)
Capability Based Security - https://news.ycombinator.com/item?id=10684129 - Dec 2015 (35 comments)
The E programming language - https://news.ycombinator.com/item?id=2497941 - April 2011 (9 comments)
E, the secure distributed pure-object platform and p2p scripting language - https://news.ycombinator.com/item?id=809714 - Sept 2009 (7 comments)
The E Language in a Walnut - https://news.ycombinator.com/item?id=70712 - Oct 2007 (1 comment)
Other threads?
If the hosted VM part is what it comes down to you also have Pony. Haven't looked at it in quite a while but it always surprised me it didn't end up more popular.
Another interesting thing that came out of the object-capability ferment around E and EROS was Darius Bacon's Idel secure virtual machine: https://github.com/darius/idel
Though no other software is as influential as JS, other currently influential ocap systems include Genode, most of the current implementations of L4 (including seL4), and CHERI.
Could someone do this on an open source browser perhaps? Or would it require some initial big chunk of work?
TypeScript is designed in such a way that type annotations can't influence the runtime behavior. This is unlike e.g. Haskell, where types can drive code generation. Happy to elaborate more if necessary.
This means that transpiling TypeScript to JavaScript consists merely of stripping the type annotations + transpiling some of the syntactic features that might not be supported by the target JS version.
The "Type Annotations" proposal (https://github.com/tc39/proposal-type-annotations), IIRC championed partly by the TS team, will allow type annotations with almost-TS-like-syntax in plain JavaScript, which will make the "stripping type annotations" step unnecessary. You would still use the TS tooling to actually type-check the code, though.
Which exact part of TS do you want to be built into browsers?
I think it would be huge if some future nodejs/web browser can parse native TS so we no longer need to deal with the mess of dev tools like ts-node and babel and wonder why some folder structure or sourcemap is not working
I used to play with E back when I was studying infosec. I was very interested in capability based security.
Also not a little ironic that a language often regarded as one of least secure has elements from one of the most secure languages ever designed!
But for all other languages there are easy compilers. Which is why WASM, apparently, is used with such languages mostly[1]
I'd expect that these runtimes can be both distributed with browsers when they become really popular, and can be reduced in size. E.g. Python's runtime is relatively large and ships with a large stdlib. Most of which won't be needed in your code, so I'd expect it to be possible to compile a runtime that only includes what your code really needs, for example.
[1] https://blog.scottlogic.com/2022/06/20/state-of-wasm-2022.ht...
Except, you know, WASM has zero access to browser APIs, and all interactions have to go through JavaScript.
And on top of that you need to load your language's entire runtime to make it work.
True, and we have to wonder why is this still the case?
Of course someone did. Check out Blazor. :)
https://dotnet.microsoft.com/en-us/apps/aspnet/web-apps/blaz...
Not really since you can't manipulate the DOM from WASM.
The "writing it to screen" is often a rather thin layer. At least in my projects.
const incfac = () => { let n = 0; return m => (m > 0 ? n += m : n) };
A more extensive example due to Norm Hardy, presuming a multiuser Scheme interpreter that supports ocap security, is this Scheme program for voting on where to have lunch: http://cap-lore.com/CapTheory/Language/Lunch.html (define (mocntr) (let ((x 0)) (cons (lambda () (let ((yet #t))
(lambda () (if yet (begin (set! yet #f) (set! x (+ 1 x)) x)))))
(lambda () x))))
(define lunchcrowd (list (lambda (x) (write (cons "for Bill" x)))
(lambda (x) (write (cons "for Bob" x))
((cdr (assoc "Mandarin" (cdr x)))))))
(define restaurants (list "Mandarin" "Casa Lupe" "Coffee Shop"))
(define (noontime) (let ((bb
(map (lambda(r) (cons r (mocntr))) restaurants)))
(for-each (lambda (e) (e (cons "Lunchtime!" (map
(lambda(r)(cons (car r) ((cadr r)))) bb)))) lunchcrowd)
(lambda ()(map (lambda(x) (cons (car x) ((cddr x)))) bb))))
You can translate this into current versions of ES straightforwardly but it doesn't get much more readable.Norm explains:
> An invocation of mocntr is made each day for each restaurant. It returns a source of options, one of which will be offered to each of the lunch crowd. The second lambda in the definition produces such an option. The variable yet in that proc remembers if the option has been taken. The third lambda produces the getter for the count.
> bb is created each day for lunch and constitutes the ballot box. It is a list of pairs <restuarant name, <option source, count getter>>. This list is iterated over first to send each vote solicitation, and then later to count the votes.
Unfortunately he's vitrified now, so if you send him questions he will answer after a long delay, if ever.
The reason for such "frozen" objects is explained in http://www.erights.org/elang/kernel/auditors/index.html.
More generally, what if you want to drop a poll into a chat channel, upload a trading bot to a cryptocurrency exchange, run an image-filtering plugin for your paint program without giving its author access to your imagery, etc.? There are lots of scenarios where fine-grained security permits useful kinds of collaboration.
const t = Object.freeze({foo: "bar"});
// throws an error in strict mode,
// silently does nothing otherwise
t.foo = "baz";
// prints "bar"
console.log(t.foo);
The tricky part is that it does not do so recursively: const t2 = Object.freeze({foo: {bar: "baz"}});
// bar is still mutable
t2.foo.bar = "oh no!";
// prints "oh no!"
console.log(t2.foo.bar);
Still, one can easily write a function to recursively do a depth-first walk on an object and make everything immutable, so this is not really a concern in practice (if anything it gives you more flexibility).Anyway, what I think Miller meant is that immutability is not the main reason why they introduced Object.freeze.
If I understand correctly, the main idea is to prevent people from inserting malicious code in the prototype chain (or anywhere else they might be able to).
Because JavaScript is prototype based I could in theory create a new Array class that uses the original Array class as its own prototype, then replace the Array class with itself. If you then create a new array it would still work like a regular one - it just goes up the prototype chain after all.
The malicious part is that this custom array class could then also override all Array methods to secretly watch your data and send stuff to the web without you noticing, or do anything else really. Because, again, it can just call the original method of its prototype to also behave as normal without anyone noticing.
Object.freeze would let you make sure none of the fundamental JavaScript objects can be tampered with.
The other thing is that you can ensure that any the library you create cannot be tampered with by third-party libraries.
If you look at the Hardened Javascript example:
const makeCounter = () => {
let count = 0;
return harden({
incr: () => (count += 1),
decr: () => (count -= 1),
});
};
The "counter object" here is mutable. I think that's what they mean.In javascript these are similar as environment closures behave sort of similar to prototype chains.
Object.freeze makes the shape (and therefore the properties) of an object immutable. It makes no guarantees about variables being closed over by a function. Those are different semantics altogether.
That feels similar to my earlier example of properties of nested objects not being affected by Object.freeze. And in this case, being able to freeze closed variables would in a sense mean exposing those variables. Which is not how closed variables work in JS (in fact it's one of the best ways to mimic "private properties" - except they're not really properties).
It's a good example of a potential gotcha though!
Nobody else uses it and no library utilizes it, most people haven't even heard of it. Yet it has expensive ramifications for the rest of the language.
Proxies for example are super cripled, and extremely hard to use, e.g. to build seamless database integrations (OOM), and super slow, with an added equality checks and whatnot on every access, because they are supposed to also serve as an API gateways within that security framework.
How many more decades do you want to wait before programming languages and with them, actual programming practice, become secure? All major languages have failed us in this aspect - and avoiding their shortcomings won't be possible without these primitives. Until people realize this, the world will have to suffer a million hacks that could have been avoided otherwise.
https://medium.com/agoric/pola-would-have-prevented-the-even...
It does require a different mindset, perhaps even a conceptual inversion to understand and apply the security model, but that doesn't make it purely academic. Yes, it will remain that way if its logical truths are not implemented, but their applications and the consequences of ignoring them are very real.
To suggest that they only do it for their own sake is incredibly presumptuous.
However, I'd argue that the security concept introduced by E is at fundamental odds with the reality of javascript programmers.
There are other language construct that would have really improved security, such as persistent data structures, good functional programming capabilities that focus on pure functions, even E's actors could be used as isolated execution contexts that communicate via said persistent data-structures.
Having just one isolation mechanism, and making it very hard to use wrong, would really address existing security concerns, instead of just throwing a bunch of security primitives that are easy to misuse at a community that neither has the capacity to use them correctly, nor really cares.
The intuition (and perhaps hope) that Javascript already has such a large install base and that, once the changes are available in all major browsers, a cultural change is possible through it seems to be the main motivator for them to focus on this language.
Even if the syntax of the language cannot be adapted to it, and people won't create constructs themselves with these primitives, there may be a chance that programmers who do not know the fundamental concepts of the theory can still enjoy its security properties by using third party libraries (heh) like SES that provide higher level primitives, e.g. to isolate other imported libraries.
I'm still skeptical myself if the focus on Javascript is the right approach, but i'd prefer their intuition to be right on this. Creating a new language will always be cleaner, but adoption is where E failed.
Proxies are there for security? It wasn't mentioned in the article and I don't see how it providers security, it only makes things easier to use, right?
Most people think of proxies as JavaScripts "method-missing", but that's really not what they are for. They are an isolation primitive to build stuff like membranes [1][2][3].
[1]: https://tvcutsem.github.io/js-membranes [2]: https://tvcutsem.github.io/membranes [3]: https://www.youtube.com/watch?v=sClk6aB_CPk&ab_channel=JSCon...
Calling this "security" is hopefully not serious. "the properties of the object can no longer be changed" yes, unless someone else just unfreezes the object.
> That step addressed a security problem: prototype poisoning, in which objects created in traditional JavaScript were all mutable and can be subverted to confuse or surveil other parts of a program by anyone who had access to them.
This is still a problem, and the "harden" function that is described doesn't actually help because the things that it relies on could be poisoned.
From a practical security perspective, none of this actually accomplished anything or protects against any kind of bad actor doing something nefarious. I guess it's maybe useful as a comparison to E, but this article could have been a lot more direct and a lot less "we once did some stuff that is academically interesting in JavaScript."
As for harden(), whether its vulnerable to it's prototype chain in the way you describe depends entirely on how it's written. That said, these aren't amateurs so I expect they know what they're doing, and transitively freezing an object graph does add important security properties.
There doesn't appear to be any unfreeze method.
>This is still a problem, and the "harden" function that is described doesn't actually help because the things that it relies on could be poisoned.
I think the threat model here is untrusted code which runs after the "harden" function completes.
(I think this article would've been better if it had discussed threat models at the beginning.)