fix(security): support XSSI prefixes with and without commas.

Some implementations use an XSSI prefix with a trailing comma, some without.
This changes Angular to support both.
This commit is contained in:
Martin Probst 2016-06-08 20:50:58 -07:00
parent 7ce0fc7d47
commit 729dc3b764
2 changed files with 14 additions and 5 deletions

View File

@ -13,7 +13,7 @@ import {Observable} from 'rxjs/Observable';
import {Observer} from 'rxjs/Observer'; import {Observer} from 'rxjs/Observer';
import {isSuccess, getResponseURL} from '../http_utils'; import {isSuccess, getResponseURL} from '../http_utils';
const XSSI_PREFIX = ')]}\',\n'; const XSSI_PREFIX = /^\)\]\}',?\n/;
/** /**
* Creates connections using `XMLHttpRequest`. Given a fully-qualified * Creates connections using `XMLHttpRequest`. Given a fully-qualified
@ -46,9 +46,7 @@ export class XHRConnection implements Connection {
// IE10) // IE10)
let body = isPresent(_xhr.response) ? _xhr.response : _xhr.responseText; let body = isPresent(_xhr.response) ? _xhr.response : _xhr.responseText;
// Implicitly strip a potential XSSI prefix. // Implicitly strip a potential XSSI prefix.
if (isString(body) && body.startsWith(XSSI_PREFIX)) { if (isString(body)) body = body.replace(XSSI_PREFIX, '');
body = body.substring(XSSI_PREFIX.length);
}
let headers = Headers.fromResponseHeaderString(_xhr.getAllResponseHeaders()); let headers = Headers.fromResponseHeaderString(_xhr.getAllResponseHeaders());
let url = getResponseURL(_xhr); let url = getResponseURL(_xhr);

View File

@ -472,6 +472,17 @@ export function main() {
existingXHRs[0].dispatchEvent('load'); existingXHRs[0].dispatchEvent('load');
})); }));
it('should strip XSSI prefixes', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
var conn = new XHRConnection(sampleRequest, new MockBrowserXHR(), new ResponseOptions());
conn.response.subscribe((res: Response) => {
expect(res.text()).toBe('{json: "object"}');
async.done();
});
existingXHRs[0].setStatusCode(200);
existingXHRs[0].setResponseText(')]}\'\n{json: "object"}');
existingXHRs[0].dispatchEvent('load');
}));
it('should strip XSSI prefixes', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { it('should strip XSSI prefixes', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
var conn = new XHRConnection(sampleRequest, new MockBrowserXHR(), new ResponseOptions()); var conn = new XHRConnection(sampleRequest, new MockBrowserXHR(), new ResponseOptions());
conn.response.subscribe((res: Response) => { conn.response.subscribe((res: Response) => {
@ -491,7 +502,7 @@ export function main() {
async.done(); async.done();
}); });
existingXHRs[0].setStatusCode(404); existingXHRs[0].setStatusCode(404);
existingXHRs[0].setResponseText(')]}\',\n{json: "object"}'); existingXHRs[0].setResponseText(')]}\'\n{json: "object"}');
existingXHRs[0].dispatchEvent('load'); existingXHRs[0].dispatchEvent('load');
})); }));