summaryrefslogtreecommitdiffstats
path: root/chrome/common/extensions/docs/static
diff options
context:
space:
mode:
authorabarth@chromium.org <abarth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-20 16:42:17 +0000
committerabarth@chromium.org <abarth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-20 16:42:17 +0000
commit5c1b42a28ecd53f8dc4b8e3f43b9818e39f04a60 (patch)
treee1af3fc8edad75c9b8f40a8a490e971d080aa3d9 /chrome/common/extensions/docs/static
parent45a19e98e7bdd706c80c29ed8e0785cfa0695a72 (diff)
downloadchromium_src-5c1b42a28ecd53f8dc4b8e3f43b9818e39f04a60.zip
chromium_src-5c1b42a28ecd53f8dc4b8e3f43b9818e39f04a60.tar.gz
chromium_src-5c1b42a28ecd53f8dc4b8e3f43b9818e39f04a60.tar.bz2
Add some security considerations to our extension docs.
BUG=26594 TEST=None, just documentation Review URL: http://codereview.chromium.org/412003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@32614 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common/extensions/docs/static')
-rw-r--r--chrome/common/extensions/docs/static/content_scripts.html60
-rw-r--r--chrome/common/extensions/docs/static/messaging.html42
-rw-r--r--chrome/common/extensions/docs/static/npapi.html20
-rw-r--r--chrome/common/extensions/docs/static/xhr.html68
4 files changed, 184 insertions, 6 deletions
diff --git a/chrome/common/extensions/docs/static/content_scripts.html b/chrome/common/extensions/docs/static/content_scripts.html
index 9c90859..80d1fc4 100644
--- a/chrome/common/extensions/docs/static/content_scripts.html
+++ b/chrome/common/extensions/docs/static/content_scripts.html
@@ -137,7 +137,7 @@ learn about the
<p>For example, consider this simple page:
<pre>hello.html
-===========
+==========
&lt;html&gt;
&lt;button id="button"&gt;click me&lt;/button&gt;
&lt;script&gt;
@@ -152,7 +152,7 @@ learn about the
<p>Now, suppose this content script was injected into hello.html:
<pre>contentscript.js
-==================
+================
console.log(greeting); // undefined
console.log(sayGreeting); // undefined
console.log(document.getElementById("button").onclick); // still undefined
@@ -174,27 +174,75 @@ document.getElementById("button").onclick = function() {
<p>An example can be accomplished using custom DOM events and storing data in a known location. Consider: </p>
<pre>http://foo.com/example.html
-================================
+===========================
var customEvent = document.createEvent('Event');
customEvent.initEvent('myCustomEvent', true, true);
function fireCustomEvent(data) {
hiddenDiv = document.getElementById('myCustomEventDiv');
- hiddenDiv.innerHTML = data
+ hiddenDiv.innerText = data
hiddenDiv.dispatchEvent(customEvent);
}</pre>
<pre>contentscript.js
-=====================
+================
var port = chrome.extension.connect();
document.getElementById('myCustomEventDiv').addEventListener('myCustomEvent', function() {
- var eventData = document.getElementById('myCustomEventDiv').innerHTML;
+ var eventData = document.getElementById('myCustomEventDiv').innerText;
port.postMessage({message: "myCustomEvent", values: eventData});
});</pre>
<p>In the above example, example.html (which is not a part of the extension) creates a custom event and then can decide to fire the event by setting the event data to a known location in the DOM and then dispatching the custom event. The content script listens for the name of the custom event on the known element and handles the event by inspecting the data of the element, and turning around to post the message to the extension process. In this way the page establishes a line of communication to the extension. The reverse is possible through similar means.</p>
+<h2 id="security-considerations">Security considerations</h2>
+
+When writing a content script, you should be aware of two security issues.
+First, be careful not to introduce security vulnerabilities into the web site
+your content script is injected into. For example, if your content script
+receives content from another web site (e.g., by <a
+href="messaging.html">asking your background page to make an
+XMLHttpRequest</a>), be careful to filter that content for <a
+href="http://en.wikipedia.org/wiki/Cross-site_scripting">cross-site
+scripting</a> attacks before injecting the content into the current page.
+For example, prefer to inject content via innerText rather than innerHTML.
+Be especially careful when retrieving HTTP content on an HTTPS page because
+the HTTP content might have been corrupted by a network <a
+href="http://en.wikipedia.org/wiki/Man-in-the-middle_attack">"man-in-the-middle"</a>
+if the user is on a hostile network.</p>
+
+<p>Second, although running your content script in an isolated world provides
+some protection from the web page, a malicious web page might still be able
+to attack your content script if you use content from the web page
+indiscriminately. For example, the following patterns are dangerous:
+<pre>contentscript.js
+================
+var data = document.getElementById("json-data")
+// WARNING! Might be evaluating an evil script!
+var parsed = eval("(" + data + ")")
+
+contentscript.js
+================
+var elmt_id = ...
+// WARNING! elmt_id might be "); ... evil script ... //"!
+window.setTimeout("animate(" + elmt_id + ")", 200);
+</pre>
+<p>Instead, prefer safer APIs that do not run scripts:</p>
+<pre>contentscript.js
+================
+var data = document.getElementById("json-data")
+// JSON.parse does not evaluate the attacker's scripts.
+var parsed = JSON.parse(data)
+
+contentscript.js
+================
+var elmt_id = ...
+// The closure form of setTimeout does not evaluate scripts.
+window.setTimeout(function() {
+ animate(elmt_id);
+}, 200);
+</pre>
+
<h2 id="extension-files">Referring to extension files</h2>
<p>
diff --git a/chrome/common/extensions/docs/static/messaging.html b/chrome/common/extensions/docs/static/messaging.html
index 4adc53a..97c0ab4 100644
--- a/chrome/common/extensions/docs/static/messaging.html
+++ b/chrome/common/extensions/docs/static/messaging.html
@@ -215,3 +215,45 @@ chrome.extension.sendRequest(laserExtensionId, {getTargetData: true},
var port = chrome.extension.connectExternal(laserExtensionId);
port.postMessage(...);
</pre>
+
+<h2 id="security-considerations">Security considerations</h2>
+
+<p>
+When receiving a message from a content script or another extension, your
+background page should be careful not to fall victim to <a
+href="http://en.wikipedia.org/wiki/Cross-site_scripting">cross-site
+scripting</a>. Specifically, avoid using dangerous APIs such as the
+below:
+</p>
+<pre>background.html
+===============
+chrome.tabs.sendRequest(tab.id, {greeting: "hello"}, function(response) {
+ // WARNING! Might be evaluating an evil script!
+ var resp = eval("(" + response.farewell + ")");
+});
+
+background.html
+===============
+chrome.tabs.sendRequest(tab.id, {greeting: "hello"}, function(response) {
+ // WARNING! Might be injecting a malicious script!
+ document.getElementById("resp").innerHTML = response.farewell;
+});
+</pre>
+<p>
+Instead, prefer safer APIs that do not run scripts:
+</p>
+<pre>background.html
+===============
+chrome.tabs.sendRequest(tab.id, {greeting: "hello"}, function(response) {
+ // JSON.parse does not evaluate the attacker's scripts.
+ var resp = JSON.parse(response.farewell);
+});
+
+background.html
+===============
+chrome.tabs.sendRequest(tab.id, {greeting: "hello"}, function(response) {
+ // innerText does not let the attacker inject HTML elements.
+ document.getElementById("resp").innerText = response.farewell;
+});
+</pre>
+
diff --git a/chrome/common/extensions/docs/static/npapi.html b/chrome/common/extensions/docs/static/npapi.html
index 817d1b3..14542a9 100644
--- a/chrome/common/extensions/docs/static/npapi.html
+++ b/chrome/common/extensions/docs/static/npapi.html
@@ -66,3 +66,23 @@ follow these steps to get your extension using it.
you can even use a content script to programmatically
insert your plugin into a web page.
</p>
+ </li>
+</ol>
+
+<h2 id="security-considerations">Security considerations</h2>
+
+<p>
+Including an NPAPI plugin in your extension is dangerous because plugins
+have unrestricted access to the local machine. If your plugin contains
+a vulnerability, an attacker might be able to exploit that vulnerability
+to install malicious software on the user's machine. Instead, avoid
+including an NPAPI plugin whenever possible.
+</p>
+
+<p>
+Marking your NPAPI plugin "public" increase the attack surface of your
+extension because the plugin is exposed directly to web content, making
+it easier for a malicious web site to manipulate your plugin. Instead,
+avoid making your NPAPI plugin public whenever possible.
+</p>
+
diff --git a/chrome/common/extensions/docs/static/xhr.html b/chrome/common/extensions/docs/static/xhr.html
index 3a10dc8..ebbd56b 100644
--- a/chrome/common/extensions/docs/static/xhr.html
+++ b/chrome/common/extensions/docs/static/xhr.html
@@ -76,5 +76,73 @@ of hosts, it must declare the permissions separately:</p>
],
</pre>
+<h2 id="security-considerations">Security considerations</h2>
+
+<p>
+When using resources retrieved via XMLHttpRequest, your background page should
+be careful not to fall victim to <a
+href="http://en.wikipedia.org/wiki/Cross-site_scripting">cross-site
+scripting</a>. Specifically, avoid using dangerous APIs such as the below:
+</p>
+<pre>background.html
+===============
+var xhr = new XMLHttpRequest();
+xhr.open("GET", "http://api.example.com/data.json", true);
+xhr.send();
+xhr.onreadystatechange = function() {
+ if (xhr.readyState == 4) {
+ // WARNING! Might be evaluating an evil script!
+ var resp = eval("(" + xhr.responseText + ")");
+ ...
+ }
+}
+
+background.html
+===============
+var xhr = new XMLHttpRequest();
+xhr.open("GET", "http://api.example.com/data.json", true);
+xhr.send();
+xhr.onreadystatechange = function() {
+ if (xhr.readyState == 4) {
+ // WARNING! Might be injecting a malicious script!
+ document.getElementById("resp").innerHTML = xhr.responseText;
+ ...
+ }
+}
+</pre>
+<p>
+Instead, prefer safer APIs that do not run scripts:
+</p>
+<pre>background.html
+===============
+var xhr = new XMLHttpRequest();
+xhr.open("GET", "http://api.example.com/data.json", true);
+xhr.send();
+xhr.onreadystatechange = function() {
+ if (xhr.readyState == 4) {
+ // JSON.parse does not evaluate the attacker's scripts.
+ var resp = JSON.parse(xhr.responseText);
+ }
+}
+
+background.html
+===============
+var xhr = new XMLHttpRequest();
+xhr.open("GET", "http://api.example.com/data.json", true);
+xhr.send();
+xhr.onreadystatechange = function() {
+ if (xhr.readyState == 4) {
+ // innerText does not let the attacker inject HTML elements.
+ document.getElementById("resp").innerText = xhr.responseText;
+ }
+}
+</pre>
+<p>
+Additionally, be especially careful of resource retrieved via HTTP. If your
+extension is used on a hostile network, an network attacker (aka a <a
+href="http://en.wikipedia.org/wiki/Man-in-the-middle_attack">"man-in-the-middle"</a>)
+could modify the response and, potentially, attack your extension. Instead,
+prefer HTTPS whenever possible.
+</p>
<!-- END AUTHORED CONTENT -->