Example: Confining a password strength-checker with COWL

COWL can be used to build several common types of application securely. Our paper describes several examples, including an encrypted document editor, an app that relies on jQuery, a third-party mashup, and a password strength checker. We will release the code for all of these soon, but for now let's see how we can confine a third-party library such as a password strength-checker.

Suppose the developer of the page https://example.com wants to use the password strength checker from http://sketchy.ru/checker.js. Maybe the developers at sketchy.ru are not malicious, but the developer doesn't trust them to write bug-free code. Note that the checker may need to communicate with sketchy.ru to fetch data that it needs to do its job. (For a more realistic library, e.g., the syntax highlighter running in this page, this is desirable functionality.) How does the developer use COWL to ensure that the checker won't leak a user's password to sketchy.ru or any other site?

Step 1: load the checker in a new labeled context // In example.com page, create new context: var checker = new LWorker("http://sketchy.ru/checker.js"); An LWorker is a lightweight labeled worker, COWL's approach to creating cheap labeled contexts. (These are similar to Note: If you are using the preliminary release of COWL, to run this code you will need to include Anis a lightweight labeled worker, COWL's approach to creating cheap labeled contexts. (These are similar to Web Workers , but labeled and run in the same thread as the parent.) This code simply creates a new context and starts running the untrusted checker code in this context. (If you are using the preliminary release of COWL, to run this code you will need to include cowl.js to use the LWorker API.)

Step 2: register handler to get result // In example.com page, register message handler waiting for result checker.onmessage = function(result) { console.log('Password is: ' + result.toString()); }; Since all communication between labeled contexts is done by message passing, we register a handler to be invoked once the checker sends us the result. Since all communication between labeled contexts is done by message passing, we register a handler to be invoked once the checker sends us the result.

Step 3: send password // Is the password sensitive? Yes, label it with example.com! var labeledPassword = new LabeledBlob(password, "http://example.com"); // Send the checker the labeled password: checker.postMessage(labeledPassword); Finally, let's send the checker the password so it can do its job. Since the password is sensitive, though, we label it with the origin it's sensitive to: example.com. Now when when the checker reads the password, it will be confined! Finally, let's send the checker the password so it can do its job. Since the password is sensitive, though, we label it with the origin it's sensitive to: example.com. Now when when the checker reads the password, it will be confined!

The checker code Our code expects the checker to use message passing. What might this code look like? Here is one possibility: // In checker.js, register handler waiting for request from parent: onmessage = function(labeledPass) { if (doneLoading) { // Taint contex to preserve privacy or password COWL.privacyLabel = COWL.privacyLabel.and(labeledPass.privacy); // Now we can read the password var password = labeledPass.blob; // Cannot communicate with sketchy.ru anymore, but can reply to parent: postMessage(checkStrength(password)); } }; // .. use XHLHttpRequest to communicate with arbitrary sites This checker code starts out unconfined: it can communicate with arbitrary web sites to fetch any data it needs. However, once it has finished doing so (indicated by doneLoading ) and the parent has supplied it the labeled password, it can proceed to check the strength of the password. Specifically, in the onmessage handler, the code extracts the password from the labeled blob--at which point COWL taints the context--and computes the strength with the checkStrength function. Once the code has inspected the password COWL confines it, preventing it from communicating arbitrarily. The code can, of course, send the containing example.com page the strength of the password. This checker code starts out unconfined: it can communicate with arbitrary web sites to fetch any data it needs. However, once it has finished doing so (indicated by) and the parent has supplied it the labeled password, it can proceed to check the strength of the password. Specifically, in thehandler, the code extracts the password from the labeled blob--at which point COWL taints the context--and computes the strength with thefunction. Once the code has inspected the password COWL confines it, preventing it from communicating arbitrarily. The code can, of course, send the containing example.com page the strength of the password.

Take-away: privacy AND functionality Even this simple example illustrates how COWL achieves two properties that are today generally mutally exclusive: the password strength checker has the flexibility to communicate as necessary, but once it actually has inspected the password, it is thereafter prevented from communicating arbitrarily so as to ensure privacy. Today developers can either opt for functionality by allowing the checker to communicate arbitrarily (even after reading sensitive data) or privacy by disallowing it from communicating at all (or not using the library in the first place).