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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 <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
2 <div id="pageData-showTOC" class="pageData">true</div>
3
4 <p>
5 Chrome's extension system enforces a fairly strict default
6 <a href="http://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specif ication.dev.html">
7 <strong>Content Security Policy (CSP)</strong>
8 </a>. Generally, the restrictions this policy imposes are straightforward to
9 work with: script must be moved out-of-line into separate JavaScript files,
10 inline event handlers must be converted to use <code>addEventListener</code>,
11 and so on. For a full walkthrough of CSP's effects on extension development,
12 please see the <a href="contentSecurityPolicy.html">Content Security Policy
13 extension documentation</a>. The default policy described in that document
14 significantly improves the overall security of extensions running in Chrome.
15 We're happy with the peace of mind it provides developers and users, and are
16 comfortable with the impact going forward.
17 </p>
18
19 <p>
20 That said, one aspect of the default restriction has proven itself
21 <a href="http://code.google.com/p/chromium/issues/detail?id=107538">
22 more problematic than expected for developers</a>. <code>eval()</code> and
23 <code>eval</code>-like constructs such as <code>new Function()</code> are used
24 in a variety of libraries for performance optimization and ease of expression.
25 Templating libraries are especially prone to this style of implementation,
26 and while some (like <a href="http://angularjs.org/">Angular.js</a>) support
27 CSP out of the box, many popular frameworks haven't yet updated to a mechanism
28 that is compatible with extensions' <code>eval</code>-less world. This
29 document describes a workaround that will allow you to keep using these
30 libraries you enjoy, but in a way that doesn't compromise security.
31 </p>
32
33 <h2>Creating a Sandbox</h2>
34
35 <p>
36 <code>eval</code> is dangerous inside an extension because the code it
37 executes has access to everything in the extension's high-permission
38 environment. A slew of powerful
39 <a href="api_index.html"><code>chrome.*</code> APIs</a> are available that
40 could have severe impact on a user's security and privacy, simple data
41 exfiltration is the least of our worries. If we remove this context, however,
42 <code>eval</code> isn't anything to worry about. The solution on offer, then,
43 is a sandbox in which <code>eval</code> can execute code without access
44 either to the extension's data or the extension's high-value APIs. No data,
45 no APIs, no problem.
46 </p>
47
48 <p>
49 We accomplish this by listing specific HTML files inside the extension package
50 as being sandboxed: add a <code>sandbox</code> attribute to the extension's
51 manifest that looks like the following:
52 </p>
53
54 <pre>{
55 ...,
56 <strong>"sandbox": {
57 "pages": ["sandbox.html"]
58 }</strong>,
59 ...
60 }</pre>
61
62 <p>
63 Whenever a page listed in the <code>pages</code> attribute is loaded, it will
64 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. :)
65 to <code>chrome.*</code> APIs. If we load this sandboxed page into our
66 extension via an <code>iframe</code>, we can pass it messages, let it act upon
67 those messages in some way, and wait for it to pass us back a result. This
68 simple messaging mechanism gives us everything we need to safely include
69 <code>eval</code>-driven code in our extension's workflow.
70 </p>
71
72 <h2>Sandbox Usage Example</h2>
73
74 <p>
75 If you'd like to dive straight into code, please grab the
76 <a href='#TODO'>sandboxing sample extension</a> and take off. It's a working
77 example of a tiny messaging API built on top of the
78 <a href="http://handlebarsjs.com/">Handlebars templating library</a>, and it
79 should give you everything you need to get going. For those of you who'd
80 like a little more explanation, let's walk through it together here.
81 </p>
82
83 <p>
84 First and foremost, <a href='#TODO'><code>sandbox.html</code></a> has been
85 included in the <a href='#TODO'><code>manifest.json</code></a> file as a
86 sandboxed page. This is important, and it's easy to forget, so please double
87 check that your sandboxed file is listed in the manifest.
88 </p>
89
90 <pre>{
91 ...,
92 <strong>"sandbox": {
93 "pages": ["sandbox.html"]
94 }</strong>,
95 ...
96 }</pre>
97
98 <p>
99 Second, we see that <a href='#TODO'><code>sandbox.html</code></a> has been
100 loaded into the extension's <a href='event_pages.html'>Event Page</a>
101 (<a href='#TODO'><code>eventpage.html</code></a>) via an <code>iframe</code>.
102 <a href='#TODO'><code>eventpage.js</code></a> contains code that addresses
103 this sandbox whenever the browser action is clicked by finding the
104 <code>iframe</code> on the page, and executing the <code>postMessage</code>
105 method on its <code>contentWindow</code>. The message is an object containing
106 two properties: <code>context</code> and <code>command</code>. We'll dive into
107 both in a moment.
108 </p>
109
110 <pre>chrome.browserAction.onClicked.addListener(function() {
111 var iframe = document.getElementById('theFrame');
112 var message = {
113 command: 'render',
114 context: {thing: 'world'}
115 };
116 iframe.contentWindow.postMessage(message, '*');
117 });</pre>
118
119 <p class="note">For general information about the <code>postMessage</code> API,
120 take a look at the <a href="https://developer.mozilla.org/en/DOM/window.postMess age">
121 <code>postMessage</code> documentation on MDN
122 </a>. It's quite complete and worth reading.</p>
123
124 <p>
125 When <code>sandbox.html</code> is loaded, it loads the Handlebars library, and
126 creates and compiles an inline template in the way Handlebars suggests:
127 </p>
128
129 <pre>&lt;script src="handlebars-1.0.0.beta.6.js"&gt;&lt;/script&gt;
130 &lt;script id="hello-world-template" type="text/x-handlebars-template"&gt;
131 &lt;div class="entry"&gt;
132 &lt;h1&gt;Hello, {{thing}}!&lt;/h1&gt;
133 &lt;/div&gt;
134 &lt;/script&gt;
135 &lt;script&gt;
136 var templates = [];
137 var source = document.getElementById('hello-world-template').innerHTML;
138 templates['hello'] = Handlebars.compile(source);
139 &lt;/script&gt;</pre>
140
141 <p>
142 This doesn't fail! Even though <code>Handlebars.compile</code> ends up using
143 <code>new Function</code>, things work exactly as expected, and we end up
144 with a compiled template in <code>templates['hello']</code>.
145 </p>
146
147 <p>
148 We'll make this template available for use by setting up a message listener
149 that accepts commands from the Event Page. We'll use the <code>command</code>
150 passed in to determine what ought to be done (you could imagine doing more
151 than simply rendering; perhaps creating templates? Perhaps managing them in
152 some way?), and the <code>context</code> will be passed into the template
153 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.
154 Page so the extension can do something useful with it later on:
155 </p>
156
157 <pre>window.addEventListener('message', function(event) {
158 var command = event.data.command;
159 var name = event.data.name || 'hello';
160 switch(command) {
161 case 'render':
162 event.source.postMessage({
163 name: name,
164 html: templates[name](event.data.context)
165 }, event.origin);
166 break;
167
168 // case 'somethingElse':
169 // ...
170 }
171 });</pre>
172
173 <p>
174 Back in the Event Page, we'll receive this message, and do something
175 interesting with the <code>html</code> data we've been passed. In this case,
176 we'll just echo it out via a <a href='notifications.html'>Desktop
177 Notification</a>, but it's entirely possible to use this HTML safely as part
178 of the extension's UI. Inserting it via <code>innerHTML</code> doesn't pose a
179 security risk, as we're protected in this context from unintentional
180 execution of inline script.
181 </p>
182
183 <p>
184 This mechanism makes templating straightforward, but it of course isn't
185 limited to templating. INSERT OTHER EXAMPLE CODE HERE.
186 </p>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698