Skip to content

Commit

Permalink
prototype: Prevent a potential security issue for cross-site ajax req…
Browse files Browse the repository at this point in the history
…uests.
  • Loading branch information
tobie committed Jan 23, 2008
1 parent dcada47 commit 02cc999
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG
@@ -1,5 +1,7 @@
*SVN*

* Prevent a potential security issue for cross-site ajax requests. [Alexey Feldgendler, sam, Tobie Langel]

* Test for attribute existence before applying more complex CSS3 selectors. Closes #10870. [arty, Tobie Langel]

* Fix "function $A" declaration inside of a conditional (confuses IE). Closes #10882. [Jacco, Andrew Dupont]
Expand Down
17 changes: 14 additions & 3 deletions src/ajax.js
Expand Up @@ -189,7 +189,7 @@ Ajax.Request = Class.create(Ajax.Base, {

var contentType = response.getHeader('Content-type');
if (this.options.evalJS == 'force'
|| (this.options.evalJS && contentType
|| (this.options.evalJS && this.isSameOrigin() && contentType
&& contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
this.evalResponse();
}
Expand All @@ -207,6 +207,15 @@ Ajax.Request = Class.create(Ajax.Base, {
}
},

isSameOrigin: function() {
var m = this.url.match(/^\s*https?:\/\/[^/]*/);
return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
protocol: location.protocol,
domain: document.domain,
port: location.port ? ':' + location.port : ''
}));
},

getHeader: function(name) {
try {
return this.transport.getResponseHeader(name) || null;
Expand Down Expand Up @@ -282,7 +291,8 @@ Ajax.Response = Class.create({
if (!json) return null;
json = decodeURIComponent(escape(json));
try {
return json.evalJSON(this.request.options.sanitizeJSON);
return json.evalJSON(this.request.options.sanitizeJSON ||
!this.request.isSameOrigin());
} catch (e) {
this.request.dispatchException(e);
}
Expand All @@ -295,7 +305,8 @@ Ajax.Response = Class.create({
this.responseText.blank())
return null;
try {
return this.responseText.evalJSON(options.sanitizeJSON);
return this.responseText.evalJSON(options.sanitizeJSON ||
!this.request.isSameOrigin());
} catch (e) {
this.request.dispatchException(e);
}
Expand Down
39 changes: 39 additions & 0 deletions test/unit/ajax.html
Expand Up @@ -410,6 +410,45 @@ <h1>Prototype Unit test file</h1>
} else {
info(message);
}
}},

testIsSameOriginMethod: function() {with(this) {
var isSameOrigin = Ajax.Request.prototype.isSameOrigin;
assert(isSameOrigin.call({ url: '/foo/bar.html' }), '/foo/bar.html');
assert(isSameOrigin.call({ url: window.location.toString() }), window.location);
assert(!isSameOrigin.call({ url: 'http://example.com' }), 'http://example.com');

if (isRunningFromRake) {
Ajax.Request.prototype.isSameOrigin = function() {
return false
};

$("content").update('same origin policy');
new Ajax.Request("/response", extendDefault({
parameters: Fixtures.js,
onComplete: function(transport) {
assertEqual("same origin policy", $("content").innerHTML);
}
}));

new Ajax.Request("/response", extendDefault({
parameters: Fixtures.invalidJson,
onException: function(request, error) {
assert(error.message.include('Badly formed JSON string'));
}
}));

new Ajax.Request("/response", extendDefault({
parameters: { 'X-JSON': '{});window.attacked = true;({}' },
onException: function(request, error) {
assert(error.message.include('Badly formed JSON string'));
}
}));

Ajax.Request.prototype.isSameOrigin = isSameOrigin;
} else {
info(message);
}
}}
});
// ]]>
Expand Down

0 comments on commit 02cc999

Please sign in to comment.