- From: Mercurial notifier <cvsmail@w3.org>
- Date: Thu, 26 May 2011 16:14:44 +0000
- To: public-dap-commits@w3.org
changeset: 18:997b3750dcd1 tag: tip user: Robin Berjon <robin@berjon.com> date: Thu May 26 18:14:35 2011 +0200 files: proposals/request-feature/Overview.html proposals/request-feature/frac-unicorner/index.html proposals/request-feature/frac-unicorner/unicorner.js proposals/request-feature/xss-pwnd/unicorner.js description: intro done diff -r d86e235b145f -r 997b3750dcd1 proposals/request-feature/Overview.html --- a/proposals/request-feature/Overview.html Thu May 26 17:06:37 2011 +0200 +++ b/proposals/request-feature/Overview.html Thu May 26 18:14:35 2011 +0200 @@ -38,28 +38,6 @@ backing implied or otherwise from any other party. </p> </section> - <!-- - - this is for XSS mitigation - - can bring in capabilities listing - - maybe use CommonJS exporting - - BASIC - - just a container, like a CommonJS transport - - var contained = new Container("wicked-cool-app.js"); - - CAPABLE - - add support for pre-declaration of capabilities similar to Feature Permissions - - var contained = new Container("even-cooler.js", { geolocation: true, - contacts: true, - fileStorage: { quota: "5Mo" } - }); - - COMMUNICATING - - like a CommonJS module (at least have exports) - - --> <section> <h2>Introduction</h2> <p> @@ -136,7 +114,101 @@ <section> <h2>Example: FRAC</h2> <p> - + We will now show how to implement the very same functionality using FRAC. You can + <a href='frac-unicorner/index.html'>try the example</a> but it will only work in a FRAC-enabled browser and + as of this writing those are few and far apart. We can look at the code however to see how it has been modified. + </p> + <p> + The first thing to note is that the changes required to the entire code are extremely minimal: + </p> + <pre class='example'> + diff -wU 1 xss-pwnd/index.html frac-unicorner/index.html + --- xss-pwnd/index.html 2011-05-26 16:58:10.000000000 +0200 + +++ frac-unicorner/index.html 2011-05-26 17:26:50.000000000 +0200 + @@ -18,6 +18,5 @@ + <script src='http://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js'></script> + <span style='color:red'>- <script src='unicorner.js'></script></span> + <script> + <span style='color:red'>- jQuery(function () { </span> + <span style='color:red'>- UI.loadEverything();</span> + <span style='color:green'>+ requestFeatures(["geolocation", "indexeddb"], ["unicorner.js"], function (unicorner) {</span> + <span style='color:green'>+ unicorner.UI.loadEverything(jQuery);</span> + }); + diff -wU 1 xss-pwnd/unicorner.js frac-unicorner/unicorner.js + --- xss-pwnd/unicorner.js 2011-05-26 17:12:03.000000000 +0200 + +++ frac-unicorner/unicorner.js 2011-05-26 17:27:16.000000000 +0200 + @@ -1,6 +1,6 @@ + <span style='color:red'>-(function (exports, $) {</span> + <span style='color:red'>- var curLocation = null, db, store;</span> + <span style='color:green'>+var curLocation = null, db, store, $;</span> + + exports.UI = { + <span style='color:red'>- loadEverything: function () {</span> + <span style='color:green'>+ loadEverything: function (jq) {</span> + <span style='color:green'>+ $ = jq;</span> + Messaging.watchLocation(); + @@ -55,2 +55 @@ + }; + <span style='color:red'>-})(window, jQuery);</span> + </pre> + <p> + We have simply: 1) removed the direct loading of the application script, 2) replaced the jQuery <code>onload</code> + handler with a call to <code>requestFeatures</code>, and 3) unwrapped the script from its self-calling + anonymous function since we don't need that protection anymore. + </p> + <p> + Loading the script is performed with the following code: + </p> + <pre class='example highlight'> + requestFeatures(["geolocation", "indexeddb"], ["unicorner.js"], function (unicorner) { + unicorner.UI.loadEverything(jQuery); + }); + </pre> + <p> + This simple call takes three parameters. The first is a list of capabilities required for the application + to execute (in this case geolocation and access to the IndexedDB local storage). By bundling these in a + single array the user agent is able to display a user interface that requests permission for all the + capabilities at once, thereby making the user experience more fluid (An example of a potential user + interface for such an approach can be seen in the + <a href='http://dev.w3.org/2009/dap/docs/feat-perms/feat-perms.html'>Feature Permissions Playground</a>.). + </p> + <p> + Second is a list of the scripts that we wish to load and provide with these capabilities (in this case + there is only one, <code>unicorner.js</code>). Those are regular Javascript pieces of code, except that + instead of sharing the same execution scope as the main one, they are encapsulated in a manner similar + to that of CommonJS [[!COMMONJS]]. They have access to the same host objects that are exposed in the main + scope (<code>navigator</code>, <code>document</code>, etc.) but global variables defined there in Javascript + are invisible to them. Conversely, their own globals are not available to the main scope. The way in which + such scripts expose their functionality is by assigning to an <code>exports</code> variable. Users of + CommonJS will be familiar with the approach. + </p> + <p> + Finally is a callback, which is called when the capabilities are accepted and the scripts have loaded. + It gets called with a list of objects, each of which corresponds to the <code>exports</code> + variable for each script. Therefore, the following code in <code>unicorner.js</code>: + </p> + <pre class='example highlight'> + exports.UI = { + loadEverything: function (jq) { + // ... + } + }; + </pre> + <p> + makes it possible to call <code class='highlight'>unicorner.UI.loadEverything(jq)</code> in the previous + example. + </p> + <p> + You will note that the XSS vulnerability is still present. However, calling <code>requestFeatures</code> + tells the user agent that the author has decided to use elevated privileges only in code loaded + through <code>requestFeatures</code> and therefore the injected code's attempt to use Geolocation + will fail. Code could be injected that calls <code>requestFeatures</code> directly, but it is strictly + limited to loading from the same origin, which also precludes this attack. + </p> + <p> + In conclusion, with the addition of a simple API and a subset of the familiar CommonJS modules, we have + both improved the user experience for web applications accessing multiple capabilities, and provided + additional protection against XSS attacks. </p> </section> </section> diff -r d86e235b145f -r 997b3750dcd1 proposals/request-feature/frac-unicorner/index.html --- a/proposals/request-feature/frac-unicorner/index.html Thu May 26 17:06:37 2011 +0200 +++ b/proposals/request-feature/frac-unicorner/index.html Thu May 26 18:14:35 2011 +0200 @@ -18,7 +18,7 @@ <script src='http://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js'></script> <script> requestFeatures(["geolocation", "indexeddb"], ["unicorner.js"], function (unicorner) { - unicorner.UI.loadEverything(); + unicorner.UI.loadEverything(jQuery); }); </script> </html> diff -r d86e235b145f -r 997b3750dcd1 proposals/request-feature/frac-unicorner/unicorner.js --- a/proposals/request-feature/frac-unicorner/unicorner.js Thu May 26 17:06:37 2011 +0200 +++ b/proposals/request-feature/frac-unicorner/unicorner.js Thu May 26 18:14:35 2011 +0200 @@ -1,7 +1,8 @@ -var curLocation = null, db, store; +var curLocation = null, db, store, $; exports.UI = { - loadEverything: function () { + loadEverything: function (jq) { + $ = jq; Messaging.watchLocation(); var idxdb = window.IndexedDB || window.mozIndexedDB || window.webkitIndexedDB, dbReq = idxdb.open("Unicorner"); diff -r d86e235b145f -r 997b3750dcd1 proposals/request-feature/xss-pwnd/unicorner.js --- a/proposals/request-feature/xss-pwnd/unicorner.js Thu May 26 17:06:37 2011 +0200 +++ b/proposals/request-feature/xss-pwnd/unicorner.js Thu May 26 18:14:35 2011 +0200 @@ -1,4 +1,3 @@ - (function (exports, $) { var curLocation = null, db, store;
Received on Thursday, 26 May 2011 16:14:46 UTC