Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4537)

Unified Diff: chrome/common/extensions/docs/static/sandboxingEval.html

Issue 10810054: Describing the `sandbox` workflow for extension developers. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/common/extensions/docs/static/sandboxingEval.html
diff --git a/chrome/common/extensions/docs/static/sandboxingEval.html b/chrome/common/extensions/docs/static/sandboxingEval.html
new file mode 100644
index 0000000000000000000000000000000000000000..1a24d33419c8e4ad561292013c098c63e981f2e2
--- /dev/null
+++ b/chrome/common/extensions/docs/static/sandboxingEval.html
@@ -0,0 +1,186 @@
+<div id="pageData-name" class="pageData">Using eval in Chrome Extensions. Safely.</div>
Mihai Parparita -not on Chrome 2012/07/25 03:00:57 This isn't in the generated docs. To get that to w
+<div id="pageData-showTOC" class="pageData">true</div>
+
+<p>
+ Chrome's extension system enforces a fairly strict default
+ <a href="http://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html">
+ <strong>Content Security Policy (CSP)</strong>
+ </a>. Generally, the restrictions this policy imposes are straightforward to
+ work with: script must be moved out-of-line into separate JavaScript files,
+ inline event handlers must be converted to use <code>addEventListener</code>,
+ and so on. For a full walkthrough of CSP's effects on extension development,
+ please see the <a href="contentSecurityPolicy.html">Content Security Policy
+ extension documentation</a>. The default policy described in that document
+ significantly improves the overall security of extensions running in Chrome.
+ We're happy with the peace of mind it provides developers and users, and are
+ comfortable with the impact going forward.
+</p>
+
+<p>
+ That said, one aspect of the default restriction has proven itself
+ <a href="http://code.google.com/p/chromium/issues/detail?id=107538">
+ more problematic than expected for developers</a>. <code>eval()</code> and
+ <code>eval</code>-like constructs such as <code>new Function()</code> are used
+ in a variety of libraries for performance optimization and ease of expression.
+ Templating libraries are especially prone to this style of implementation,
+ and while some (like <a href="http://angularjs.org/">Angular.js</a>) support
+ CSP out of the box, many popular frameworks haven't yet updated to a mechanism
+ that is compatible with extensions' <code>eval</code>-less world. This
+ document describes a workaround that will allow you to keep using these
+ libraries you enjoy, but in a way that doesn't compromise security.
+</p>
+
+<h2>Creating a Sandbox</h2>
+
+<p>
+ <code>eval</code> is dangerous inside an extension because the code it
+ executes has access to everything in the extension's high-permission
+ environment. A slew of powerful
+ <a href="api_index.html"><code>chrome.*</code> APIs</a> are available that
+ could have severe impact on a user's security and privacy, simple data
+ exfiltration is the least of our worries. If we remove this context, however,
+ <code>eval</code> isn't anything to worry about. The solution on offer, then,
+ is a sandbox in which <code>eval</code> can execute code without access
+ either to the extension's data or the extension's high-value APIs. No data,
+ no APIs, no problem.
+</p>
+
+<p>
+ We accomplish this by listing specific HTML files inside the extension package
+ as being sandboxed: add a <code>sandbox</code> attribute to the extension's
+ manifest that looks like the following:
+</p>
+
+<pre>{
+ ...,
+ <strong>"sandbox": {
+ "pages": ["sandbox.html"]
+ }</strong>,
+ ...
+}</pre>
+
+<p>
+ Whenever a page listed in the <code>pages</code> attribute is loaded, it will
+ be moved to a <em>unique origin(#TODO: link)</em>, and will be denied access
Mihai Parparita -not on Chrome 2012/07/25 03:00:57 http://www.whatwg.org/specs/web-apps/current-work/
Mike West 2012/07/26 12:51:46 That's good enough, I think. :)
+ to <code>chrome.*</code> APIs. If we load this sandboxed page into our
+ extension via an <code>iframe</code>, we can pass it messages, let it act upon
+ those messages in some way, and wait for it to pass us back a result. This
+ simple messaging mechanism gives us everything we need to safely include
+ <code>eval</code>-driven code in our extension's workflow.
+</p>
+
+<h2>Sandbox Usage Example</h2>
+
+<p>
+ If you'd like to dive straight into code, please grab the
+ <a href='#TODO'>sandboxing sample extension</a> and take off. It's a working
+ example of a tiny messaging API built on top of the
+ <a href="http://handlebarsjs.com/">Handlebars templating library</a>, and it
+ should give you everything you need to get going. For those of you who'd
+ like a little more explanation, let's walk through it together here.
+</p>
+
+<p>
+ First and foremost, <a href='#TODO'><code>sandbox.html</code></a> has been
+ included in the <a href='#TODO'><code>manifest.json</code></a> file as a
+ sandboxed page. This is important, and it's easy to forget, so please double
+ check that your sandboxed file is listed in the manifest.
+</p>
+
+<pre>{
+ ...,
+ <strong>"sandbox": {
+ "pages": ["sandbox.html"]
+ }</strong>,
+ ...
+}</pre>
+
+<p>
+ Second, we see that <a href='#TODO'><code>sandbox.html</code></a> has been
+ loaded into the extension's <a href='event_pages.html'>Event Page</a>
+ (<a href='#TODO'><code>eventpage.html</code></a>) via an <code>iframe</code>.
+ <a href='#TODO'><code>eventpage.js</code></a> contains code that addresses
+ this sandbox whenever the browser action is clicked by finding the
+ <code>iframe</code> on the page, and executing the <code>postMessage</code>
+ method on its <code>contentWindow</code>. The message is an object containing
+ two properties: <code>context</code> and <code>command</code>. We'll dive into
+ both in a moment.
+</p>
+
+<pre>chrome.browserAction.onClicked.addListener(function() {
+ var iframe = document.getElementById('theFrame');
+ var message = {
+ command: 'render',
+ context: {thing: 'world'}
+ };
+ iframe.contentWindow.postMessage(message, '*');
+});</pre>
+
+<p class="note">For general information about the <code>postMessage</code> API,
+take a look at the <a href="https://developer.mozilla.org/en/DOM/window.postMessage">
+ <code>postMessage</code> documentation on MDN
+</a>. It's quite complete and worth reading.</p>
+
+<p>
+ When <code>sandbox.html</code> is loaded, it loads the Handlebars library, and
+ creates and compiles an inline template in the way Handlebars suggests:
+</p>
+
+<pre>&lt;script src="handlebars-1.0.0.beta.6.js"&gt;&lt;/script&gt;
+&lt;script id="hello-world-template" type="text/x-handlebars-template"&gt;
+ &lt;div class="entry"&gt;
+ &lt;h1&gt;Hello, {{thing}}!&lt;/h1&gt;
+ &lt;/div&gt;
+&lt;/script&gt;
+&lt;script&gt;
+ var templates = [];
+ var source = document.getElementById('hello-world-template').innerHTML;
+ templates['hello'] = Handlebars.compile(source);
+&lt;/script&gt;</pre>
+
+<p>
+ This doesn't fail! Even though <code>Handlebars.compile</code> ends up using
+ <code>new Function</code>, things work exactly as expected, and we end up
+ with a compiled template in <code>templates['hello']</code>.
+</p>
+
+<p>
+ We'll make this template available for use by setting up a message listener
+ that accepts commands from the Event Page. We'll use the <code>command</code>
+ passed in to determine what ought to be done (you could imagine doing more
+ than simply rendering; perhaps creating templates? Perhaps managing them in
+ some way?), and the <code>context</code> will be passed into the template
+ directly for rendering. The rendered HTML will be passed back to the Event
Mihai Parparita -not on Chrome 2012/07/25 03:00:57 You may want to mention that you can't pass back t
Mike West 2012/07/26 12:51:46 Done.
+ Page so the extension can do something useful with it later on:
+</p>
+
+<pre>window.addEventListener('message', function(event) {
+ var command = event.data.command;
+ var name = event.data.name || 'hello';
+ switch(command) {
+ case 'render':
+ event.source.postMessage({
+ name: name,
+ html: templates[name](event.data.context)
+ }, event.origin);
+ break;
+
+ // case 'somethingElse':
+ // ...
+ }
+});</pre>
+
+<p>
+ Back in the Event Page, we'll receive this message, and do something
+ interesting with the <code>html</code> data we've been passed. In this case,
+ we'll just echo it out via a <a href='notifications.html'>Desktop
+ Notification</a>, but it's entirely possible to use this HTML safely as part
+ of the extension's UI. Inserting it via <code>innerHTML</code> doesn't pose a
+ security risk, as we're protected in this context from unintentional
+ execution of inline script.
+</p>
+
+<p>
+ This mechanism makes templating straightforward, but it of course isn't
+ limited to templating. INSERT OTHER EXAMPLE CODE HERE.
+</p>

Powered by Google App Engine
This is Rietveld 408576698