Skip to content

Commit

Permalink
feat: Set nosniff for JSONP responses (#38)
Browse files Browse the repository at this point in the history
  • Loading branch information
onebytegone committed Mar 22, 2019
1 parent 8b9a841 commit d558ca1
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 10 deletions.
10 changes: 9 additions & 1 deletion src/Response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -476,8 +476,16 @@ export default class Response {
.replace(/\u2028/g, '\\u2028')
.replace(/\u2029/g, '\\u2029');

// NOTE: The `/**/` is a security mitigation for "Rosetta Flash JSONP abuse", see
// silvermine/lambda-express#38. The `typeof` is to prevent errors on the client
// if the callback function doesn't exist, see expressjs/express#1773.
this._body = `/**/ typeof ${callbackFunctionName} === 'function' && ${callbackFunctionName}(${stringified});`;
return this.type('text/javascript; charset=utf-8').end();

return this.type('text/javascript; charset=utf-8')
// `nosniff` is set to mitigate "Rosetta Flash JSONP abuse", see
// silvermine/lambda-express#38
.set('X-Content-Type-Options', 'nosniff')
.end();
}

return this.json(o);
Expand Down
20 changes: 11 additions & 9 deletions tests/Response.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,8 @@ describe('Response', () => {

if (expectsJsonpResponse) {
output.multiValueHeaders['Content-Type'] = [ 'text/javascript; charset=utf-8' ];
// See silvermine/lambda-express#38
output.multiValueHeaders['X-Content-Type-Options'] = [ 'nosniff' ];
} else {
output.multiValueHeaders['Content-Type'] = [ 'application/json; charset=utf-8' ];
}
Expand Down Expand Up @@ -1044,21 +1046,21 @@ describe('Response', () => {
let response: TestResponse;

beforeEach(() => {
response = new TestResponse(app, sampleReq, () => {});
response = new TestResponse(app, sampleReq, _.noop);
});

it('returns true for valid JSONP callbacks', () => {
expect(response._isValidJSONPCallback('callback')).to.be.true;
expect(response._isValidJSONPCallback('_abc')).to.be.true;
expect(response._isValidJSONPCallback('$')).to.be.true;
expect(response._isValidJSONPCallback('funcs[123]')).to.be.true;
expect(response._isValidJSONPCallback('callback')).to.strictlyEqual(true);
expect(response._isValidJSONPCallback('_abc')).to.strictlyEqual(true);
expect(response._isValidJSONPCallback('$')).to.strictlyEqual(true);
expect(response._isValidJSONPCallback('funcs[123]')).to.strictlyEqual(true);
});

it('returns false for invalid JSONP callbacks', () => {
expect(response._isValidJSONPCallback()).to.be.false;
expect(response._isValidJSONPCallback(undefined)).to.be.false;
expect(response._isValidJSONPCallback('')).to.be.false;
expect(response._isValidJSONPCallback('bad;func()')).to.be.false;
expect(response._isValidJSONPCallback()).to.strictlyEqual(false);
expect(response._isValidJSONPCallback(undefined)).to.strictlyEqual(false);
expect(response._isValidJSONPCallback('')).to.strictlyEqual(false);
expect(response._isValidJSONPCallback('bad;func()')).to.strictlyEqual(false);
});
});

Expand Down

0 comments on commit d558ca1

Please sign in to comment.