1 <h1>Cross-Origin XMLHttpRequest
</h1>
5 Regular web pages can use the
6 <a href=
"http://www.w3.org/TR/XMLHttpRequest/">XMLHttpRequest
</a>
7 object to send and receive data from remote servers,
8 but they're limited by the
9 <a href=
"http://en.wikipedia.org/wiki/Same_origin_policy">same origin policy
</a>.
10 Extensions aren't so limited.
11 An extension can talk to remote servers outside of its origin,
12 as long as it first requests cross-origin permissions.
</p>
14 <h2 id=
"extension-origin">Extension origin
</h2>
15 <p>Each running extension exists within its own separate security origin. Without
16 requesting additional privileges, the extension can use
17 XMLHttpRequest to get resources within its installation. For example, if
18 an extension contains a JSON configuration file called
<code>config.json
</code>,
19 in a
<code>config_resources
</code> folder, the extension can retrieve the file's contents like
23 var xhr = new XMLHttpRequest();
24 xhr.onreadystatechange = handleStateChange; // Implemented elsewhere.
25 xhr.open(
"GET", chrome.extension.getURL('/config_resources/config.json'), true);
29 <p>If the extension attempts to use a security origin other than itself,
30 say http://www.google.com,
31 the browser disallows it
32 unless the extension has requested the appropriate cross-origin permissions.
35 <h2 id=
"requesting-permission">Requesting cross-origin permissions
</h2>
37 <p>By adding hosts or host match patterns (or both) to the
38 <a href=
"declare_permissions">permissions
</a> section of the
39 <a href=
"manifest">manifest
</a> file, the extension can request access to
40 remote servers outside of its origin.
</p>
42 <pre data-filename=
"manifest.json">
44 "name":
"My extension",
47 "http://www.google.com/"
53 <p>Cross-origin permission values can be fully qualified host names,
57 <li> "http://www.google.com/" </li>
58 <li> "http://www.gmail.com/" </li>
61 <p>Or they can be match patterns, like these:
</p>
64 <li> "http://*.google.com/" </li>
65 <li> "http://*/" </li>
69 A match pattern of
"http://*/" allows HTTP access to all reachable domains.
71 match patterns are similar to
<a href=
"match_patterns">content script
73 but any path information following the host is ignored.
</p>
75 <p>Also note that access is granted both by host and by scheme. If an extension
76 wants both secure and non-secure HTTP access to a given host or set
77 of hosts, it must declare the permissions separately:
</p>
79 <pre data-filename=
"manifest.json">
81 "http://www.google.com/",
82 "https://www.google.com/"
86 <h2 id=
"security-considerations">Security considerations
</h2>
89 When using resources retrieved via XMLHttpRequest, your background page should
90 be careful not to fall victim to
<a
91 href=
"http://en.wikipedia.org/wiki/Cross-site_scripting">cross-site
92 scripting
</a>. Specifically, avoid using dangerous APIs such as the below:
94 <pre data-filename=
"background.js">
95 var xhr = new XMLHttpRequest();
96 xhr.open(
"GET",
"http://api.example.com/data.json", true);
97 xhr.onreadystatechange = function() {
98 if (xhr.readyState ==
4) {
99 // WARNING! Might be evaluating an evil script!
100 var resp = eval(
"(" + xhr.responseText +
")");
106 <pre data-filename=
"background.js">
107 var xhr = new XMLHttpRequest();
108 xhr.open(
"GET",
"http://api.example.com/data.json", true);
109 xhr.onreadystatechange = function() {
110 if (xhr.readyState ==
4) {
111 // WARNING! Might be injecting a malicious script!
112 document.getElementById(
"resp").innerHTML = xhr.responseText;
119 Instead, prefer safer APIs that do not run scripts:
121 <pre data-filename=
"background.js">
122 var xhr = new XMLHttpRequest();
123 xhr.open(
"GET",
"http://api.example.com/data.json", true);
124 xhr.onreadystatechange = function() {
125 if (xhr.readyState ==
4) {
126 // JSON.parse does not evaluate the attacker's scripts.
127 var resp = JSON.parse(xhr.responseText);
132 <pre data-filename=
"background.js">
133 var xhr = new XMLHttpRequest();
134 xhr.open(
"GET",
"http://api.example.com/data.json", true);
135 xhr.onreadystatechange = function() {
136 if (xhr.readyState ==
4) {
137 // innerText does not let the attacker inject HTML elements.
138 document.getElementById(
"resp").innerText = xhr.responseText;
144 Additionally, be especially careful of resources retrieved via HTTP. If your
145 extension is used on a hostile network, an network attacker (aka a
<a
146 href=
"http://en.wikipedia.org/wiki/Man-in-the-middle_attack">"man-in-the-middle"</a>)
147 could modify the response and, potentially, attack your extension. Instead,
148 prefer HTTPS whenever possible.
151 <h3 id=
"interaction-with-csp">Interaction with Content Security Policy
</h3>
154 If you modify the default
<a href=
"contentSecurityPolicy">Content
155 Security Policy
</a> for apps or extensions by adding a
156 <code>content_security_policy
</code> attribute to your manifest, you'll need to
157 ensure that any hosts to which you'd like to connect are allowed. While the
158 default policy doesn't restrict connections to hosts, be careful when explicitly
159 adding either the
<code>connect-src
</code> or
<code>default-src
</code>