From 004ea7c96f3805a7d0f5fad5332e6290fddac979 Mon Sep 17 00:00:00 2001 From: Arlo Breault Date: Mon, 31 Oct 2016 10:35:19 -0700 Subject: [PATCH] T149504: Fix reflected XSS Change-Id: I850e3fe756cb1f9d754b16c9c2be2996eaef4e9c --- lib/api/apiUtils.js | 15 +++++++++------ lib/api/routes.js | 6 +++--- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/lib/api/apiUtils.js b/lib/api/apiUtils.js index e3d77e9..ee490ea 100644 --- a/lib/api/apiUtils.js +++ b/lib/api/apiUtils.js @@ -9,6 +9,7 @@ var contentType = require('content-type'); var Diff = require('../utils/Diff.js').Diff; var DU = require('../utils/DOMUtils.js').DOMUtils; +var Util = require('../utils/Util.js').Util; var PegTokenizer = require('../wt2html/tokenizer.js').PegTokenizer; var Promise = require('../utils/promise.js'); var PHPParseRequest = require('../mw/ApiRequest.js').PHPParseRequest; @@ -67,13 +68,11 @@ apiUtils.setHeader = function(res, env, name, value) { * @method * @param {Response} res The response object from our routing function. * @param {MWParserEnvironment} env - * @param {Buffer|String|Array|Object} body - * Buffers are sent with Content-Type application/octet-stream. - * Strings are sent with Content-Type text/html. - * Arrays and Objects are JSON-encoded. + * @param {String} body * @param {Number} [status] HTTP status code + * @param {Boolean} [omitEscape] Be explicit about omitting escaping. */ -apiUtils.sendResponse = function(res, env, body, status) { +apiUtils.sendResponse = function(res, env, body, status, omitEscape) { if (env.responseSent) { return; } else { @@ -81,6 +80,10 @@ apiUtils.sendResponse = function(res, env, body, status) { if (status) { res.status(status); } + body = String(body); + if (!omitEscape) { + body = Util.entityEncodeAll(body); + } res.send(body); // Flush log buffer for linter env.log('end/response'); @@ -515,6 +518,6 @@ apiUtils.wt2htmlRes = function(env, res, html, pb) { apiUtils.jsonResponse(res, env, response); } else { apiUtils.setHeader(res, env, 'content-type', apiUtils.htmlContentType(env)); - apiUtils.sendResponse(res, env, html); + apiUtils.sendResponse(res, env, html, undefined, true); } }; diff --git a/lib/api/routes.js b/lib/api/routes.js index 4da5f5e..1837285 100644 --- a/lib/api/routes.js +++ b/lib/api/routes.js @@ -31,7 +31,7 @@ module.exports = function(parsoidConfig, processLogger) { err.httpStatus = httpStatus || 404; err.suppressLoggingStack = true; processLogger.log('fatal/request', err); - apiUtils.sendResponse(res, {}, text, err.httpStatus); + apiUtils.sendResponse(res, { log: function() {} }, text, err.httpStatus); }; // Middlewares @@ -679,7 +679,7 @@ module.exports = function(parsoidConfig, processLogger) { } apiUtils.logTime(env, res, 'serializing'); apiUtils.setHeader(res, env, 'content-type', apiUtils.wikitextContentType(env)); - apiUtils.sendResponse(res, env, output); + apiUtils.sendResponse(res, env, output, undefined, true); }); }); @@ -737,7 +737,7 @@ module.exports = function(parsoidConfig, processLogger) { if (env.page.meta && env.page.meta.revision && env.page.meta.revision.contentmodel) { apiUtils.setHeader(res, env, 'x-contentmodel', env.page.meta.revision.contentmodel); } - apiUtils.sendResponse(res, env, env.page.src); + apiUtils.sendResponse(res, env, env.page.src, undefined, true); }); } else { p = wt2html(req, res); -- 2.10.2