On Mon, Aug 18, 2008 at 5:59 PM, Brendan Eich <[EMAIL PROTECTED]> wrote: > On Aug 18, 2008, at 5:25 PM, [EMAIL PROTECTED] wrote: >> Even in Caja, it's possible for one module to import another. What >> needs to be passed down is *authority*, not the ability to execute >> code. > > I was asking, I'm happy with an answer. But what's the requirement, > exactly? Can you give an example?
I'll back into this topic, in a way. From MarkM's thesis, page 77, caption to figure 8.2 -- Authority is the Ability to Cause Effects. If 1) Bob has permission to talk to Alice, 2) Alice has permission to write /etc/passwd, and 3) Alice chooses to write there any text Bob asks her to, then Bob has authority to write /etc/passwd. Loading a module in itself *may* cause effects (e.g., if the code is retrieved via HTTP). Otherwise, by executing this code, the entity importing the module may only consume memory and CPU time; it gains no new authority that it did not have before. (And, strictly speaking, the authority to load code should properly be granted by the importer of a module.) This requirement is driven by the desire to eliminate *ambient* authority: a piece of code should not have abilities to cause effects that have not been explicitly granted to it. For example, in the Unix example, any process has the ambient authority to read a large subset of the files on the system, regardless of whether these are needed for the task at hand. To quote a classic example, when I write: cp x.txt y.txt the "cp" process can attempt to read /etc/passwd and, if successful, open a socket and send the contents to the "evil.com" server. Yet it needed only to read "x.txt" and write "y.txt" and, were it so confined, the damage it could cause would be limited to corrupting the contents of "y.txt". This damage is consistent with a simple causal model: "cp" can only damage the things I tell it to work on, and nothing else. And finally, such damage, being narrowly constrained, is now such that there is practically no reasonable economic or other incentive for authoring a malicious "cp". >From MarkM's thesis, page 16: The Principle of Least Authority (POLA) recommends that you grant each program only the authority it needs to do its job [MS03]. and this, as I hopefully motivated, is why we need to be sure that a module gets authority only explicitly, from its invoker. A capability is just an object reference that conveys authority. Typically, it is an object that, directly or transitively, can cause effects such as modifying valuable data held by some module; making changes to stable storage; displaying information on an output device; reading an input device; using the network; etc. A deep vision of capability systems would be that, on a computer system, the ability to cause effects at a primitive level -- essentially, access to hardware devices -- is owned by some powerful module instances which attenuate that into fine-grained objects, each of which represents some reasonable chunk (e.g., creating a connection to a specific host, or writing to a specific rectangle of the screen, or communicating in read-only fashion with a specific USB mass storage device). Careful interaction between modules in the system, keeping POLA in mind, ensures that everyone gets just the authority they need. The wiring of capabilities can be done by module configuration, but an important source of wiring information is the end-user. A deep capability system exposes to the end-user the ability to divvy up their authority between the modules to which they have access. For example, given a "stock tracking gadget" module, I may create two instances: one to hold my private information about what stocks I own, and another that just displays some information I consider interesting. The first I keep to myself, but I publish the second on my public profile page. Importantly, the fact that these are two instances of the same code does not grant them the ability to communicate; since I have not wired up my private instance to anything in my public profile, I know that my data is safe. In fact, the classic rewriting of the "cp" example is to simply pass it file descriptors, rather than file names: cp < x.txt > y.txt Thus redefined, "cp" needs no ambient access to any files; everything it needs is in its arguments or its Unix file descriptors, and that is all provided by its parent process. POLA is satisfied. (The fact that pretty much all Unices give "cp" the ambient authority to do pretty much anything else, even under these circumstances, is, if one is to take a polemical ocap perspective, simply a bug.) > I thought you suggested that a few built-ins (Function, Number, not Date) > were safe to populate in a global scope, "above" a module's apparent top > lexical scope. A safe (immutable, I hope) top-level. Do I have that right? Yes, that was my suggestion. > Your post asserted that responsibility for naming a module belongs to the > importer (requirer? ugh). That could be the whole truth, or half of it. > Provider and requirer might both want to use distinct names. > If requires consulted a different namespace from the property map of any > object (especially of the global object), would that be insecure? It depends on who gets to populate the map; more below.... > objcap research ... (sort of like I'm being inducted into a new religion). Your point? Oh wait, here's comes the hat. Give generously. };-> > Could you expand on why it's inevitably insecure to have a module system > with self-named modules accessible in some namespace built up by special > forms such as Dave's module syntax? Right, absolutely. The problem is that modules have an incentive to lie about their names. Let's say I rely on a module called "PRand" to generate pseudo-random numbers, and this is important for the integrity of my algorithm. Let's also say I load a number of other modules. I am now vulnerable to any of these other modules registering itself under the name "PRand" and returning the number 1 every time, thus breaking my code. While I am not vulnerable to any module I did not load, I am now equally vulnerable to all the modules I load. Thus (a) it is very difficult for me to reason clearly about the composition of attacks my subordinate modules can mount; and (b) I cannot meaningfully choose to trust one of them more than the others since they can masquerade in this way. Clearly, I still rely on the component I am calling "fetchModule" to -- well -- fetch the correct module and not lie. And I *must* rely on my parent to give me a correct "fetchModule". But, by avoiding self-named modules, it is *possible* for me to build a "fetchModule" that returns the right answer for the things that I care about, and is not vulnerable to the misbehavior of stuff that it cannot control. Ihab -- Ihab A.B. Awad, Palo Alto, CA _______________________________________________ Es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

