Backport security fixes to 3.x branch
This commit is contained in:
@@ -212,7 +212,13 @@ function registerDefaultHelpers(instance) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
instance.registerHelper('lookup', function(obj, field) {
|
instance.registerHelper('lookup', function(obj, field) {
|
||||||
return obj && obj[field];
|
if (!obj) {
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
if (field === 'constructor' && !obj.propertyIsEnumerable(field)) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return obj[field];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ JavaScriptCompiler.prototype = {
|
|||||||
// PUBLIC API: You can override these methods in a subclass to provide
|
// PUBLIC API: You can override these methods in a subclass to provide
|
||||||
// alternative compiled forms for name lookup and buffering semantics
|
// alternative compiled forms for name lookup and buffering semantics
|
||||||
nameLookup: function(parent, name /* , type*/) {
|
nameLookup: function(parent, name /* , type*/) {
|
||||||
|
if (name === 'constructor') {
|
||||||
|
return ['(', parent, '.propertyIsEnumerable(\'constructor\') ? ', parent, '.constructor : undefined', ')'];
|
||||||
|
}
|
||||||
if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
|
if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
|
||||||
return [parent, '.', name];
|
return [parent, '.', name];
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
describe('security issues', function() {
|
||||||
|
describe('GH-1495: Prevent Remote Code Execution via constructor', function() {
|
||||||
|
it('should not allow constructors to be accessed', function() {
|
||||||
|
shouldCompileTo('{{constructor.name}}', {}, '');
|
||||||
|
shouldCompileTo('{{lookup (lookup this "constructor") "name"}}', {}, '');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow the "constructor" property to be accessed if it is enumerable', function() {
|
||||||
|
shouldCompileTo('{{constructor.name}}', {'constructor': {
|
||||||
|
'name': 'here we go'
|
||||||
|
}}, 'here we go');
|
||||||
|
shouldCompileTo('{{lookup (lookup this "constructor") "name"}}', {'constructor': {
|
||||||
|
'name': 'here we go'
|
||||||
|
}}, 'here we go');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow prototype properties that are not constructors', function() {
|
||||||
|
function TestClass() {
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(TestClass.prototype, 'abc', {
|
||||||
|
get: function() {
|
||||||
|
return 'xyz';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
shouldCompileTo('{{#with this}}{{this.abc}}{{/with}}',
|
||||||
|
new TestClass(), 'xyz');
|
||||||
|
shouldCompileTo('{{#with this}}{{lookup this "abc"}}{{/with}}',
|
||||||
|
new TestClass(), 'xyz');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user