feat(security): strip XSSI prefix from XHR responses.
This commit is contained in:
parent
9099160038
commit
df1b1f6957
|
@ -6,11 +6,13 @@ import {Headers} from '../headers';
|
|||
import {ResponseOptions} from '../base_response_options';
|
||||
import {Injectable} from '@angular/core';
|
||||
import {BrowserXhr} from './browser_xhr';
|
||||
import {isPresent} from '../../src/facade/lang';
|
||||
import {isPresent, isString} from '../../src/facade/lang';
|
||||
import {Observable} from 'rxjs/Observable';
|
||||
import {Observer} from 'rxjs/Observer';
|
||||
import {isSuccess, getResponseURL} from '../http_utils';
|
||||
|
||||
const XSSI_PREFIX = ')]}\',\n';
|
||||
|
||||
/**
|
||||
* Creates connections using `XMLHttpRequest`. Given a fully-qualified
|
||||
* request, an `XHRConnection` will immediately create an `XMLHttpRequest` object and send the
|
||||
|
@ -32,13 +34,17 @@ export class XHRConnection implements Connection {
|
|||
this.response = new Observable<Response>((responseObserver: Observer<Response>) => {
|
||||
let _xhr: XMLHttpRequest = browserXHR.build();
|
||||
_xhr.open(RequestMethod[req.method].toUpperCase(), req.url);
|
||||
|
||||
// load event handler
|
||||
let onLoad = () => {
|
||||
// responseText is the old-school way of retrieving response (supported by IE8 & 9)
|
||||
// response/responseType properties were introduced in XHR Level2 spec (supported by
|
||||
// IE10)
|
||||
let body = isPresent(_xhr.response) ? _xhr.response : _xhr.responseText;
|
||||
|
||||
// Implicitly strip a potential XSSI prefix.
|
||||
if (isString(body) && body.startsWith(XSSI_PREFIX)) {
|
||||
body = body.substring(XSSI_PREFIX.length);
|
||||
}
|
||||
let headers = Headers.fromResponseHeaderString(_xhr.getAllResponseHeaders());
|
||||
|
||||
let url = getResponseURL(_xhr);
|
||||
|
|
|
@ -273,6 +273,29 @@ export function main() {
|
|||
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 prefix from errors', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
||||
var conn =
|
||||
new XHRConnection(sampleRequest, new MockBrowserXHR(), new ResponseOptions());
|
||||
conn.response.subscribe(null, (res: Response) => {
|
||||
expect(res.text()).toBe('{json: "object"}');
|
||||
async.done();
|
||||
});
|
||||
existingXHRs[0].setStatusCode(404);
|
||||
existingXHRs[0].setResponseText(')]}\',\n{json: "object"}');
|
||||
existingXHRs[0].dispatchEvent('load');
|
||||
}));
|
||||
|
||||
it('should parse response headers and add them to the response',
|
||||
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
||||
var statusCode = 200;
|
||||
|
|
Loading…
Reference in New Issue