Skip to content

Commit ced5d04

Browse files
committed
Create Objects without prototypes.
This generally helps mitigate prototype pollution: even if another library allows prototype pollution, ejs will not allow escalating this into Remote Code Execution.
1 parent 15ee698 commit ced5d04

File tree

2 files changed

+16
-10
lines changed

2 files changed

+16
-10
lines changed

lib/ejs.js

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
* @public
4545
*/
4646

47+
require('core-js/features/object/create');
48+
4749
var fs = require('fs');
4850
var path = require('path');
4951
var utils = require('./utils');
@@ -306,7 +308,7 @@ function fileLoader(filePath){
306308
*/
307309

308310
function includeFile(path, options) {
309-
var opts = utils.shallowCopy({}, options);
311+
var opts = utils.shallowCopy(Object.create(null), options);
310312
opts.filename = getIncludePath(path, opts);
311313
if (typeof options.includer === 'function') {
312314
var includerResult = options.includer(path, opts.filename);
@@ -412,8 +414,8 @@ exports.compile = function compile(template, opts) {
412414
*/
413415

414416
exports.render = function (template, d, o) {
415-
var data = d || {};
416-
var opts = o || {};
417+
var data = d || Object.create(null);
418+
var opts = o || Object.create(null);
417419

418420
// No options object -- if there are optiony names
419421
// in the data, copy them to options
@@ -484,7 +486,7 @@ exports.renderFile = function () {
484486
opts.filename = filename;
485487
}
486488
else {
487-
data = {};
489+
data = Object.create(null);
488490
}
489491

490492
return tryHandleCache(opts, data, cb);
@@ -506,8 +508,8 @@ exports.clearCache = function () {
506508
};
507509

508510
function Template(text, opts) {
509-
opts = opts || {};
510-
var options = {};
511+
opts = opts || Object.create(null);
512+
var options = Object.create(null);
511513
this.templateText = text;
512514
/** @type {string | null} */
513515
this.mode = null;
@@ -597,7 +599,8 @@ Template.prototype = {
597599
throw new Error('localsName is not a valid JS identifier.');
598600
}
599601
if (opts.destructuredLocals && opts.destructuredLocals.length) {
600-
var destructuring = ' var __locals = (' + opts.localsName + ' || {}),\n';
602+
var destructuring = ' var __locals = (' + opts.localsName +
603+
' || Object.create(null)),\n';
601604
for (var i = 0; i < opts.destructuredLocals.length; i++) {
602605
var name = opts.destructuredLocals[i];
603606
if (!_JS_IDENTIFIER.test(name)) {
@@ -611,7 +614,8 @@ Template.prototype = {
611614
prepended += destructuring + ';\n';
612615
}
613616
if (opts._with !== false) {
614-
prepended += ' with (' + opts.localsName + ' || {}) {' + '\n';
617+
prepended += ' with (' + opts.localsName
618+
+ ' || Object.create(null)) {' + '\n';
615619
appended += ' }' + '\n';
616620
}
617621
appended += ' return __output;' + '\n';
@@ -693,13 +697,14 @@ Template.prototype = {
693697
// Adds a local `include` function which allows full recursive include
694698
var returnedFn = opts.client ? fn : function anonymous(data) {
695699
var include = function (path, includeData) {
696-
var d = utils.shallowCopy({}, data);
700+
var d = utils.shallowCopy(Object.create(null), data);
697701
if (includeData) {
698702
d = utils.shallowCopy(d, includeData);
699703
}
700704
return includeFile(path, opts)(d);
701705
};
702-
return fn.apply(opts.context, [data || {}, escapeFn, include, rethrow]);
706+
return fn.apply(opts.context,
707+
[data || Object.create(null), escapeFn, include, rethrow]);
703708
};
704709
if (opts.filename && typeof Object.defineProperty === 'function') {
705710
var filename = opts.filename;

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"bugs": "https://github.com/mde/ejs/issues",
2323
"homepage": "https://github.com/mde/ejs",
2424
"dependencies": {
25+
"core-js": "^3.13.1",
2526
"jake": "^10.6.1"
2627
},
2728
"devDependencies": {

0 commit comments

Comments
 (0)