fix: disallow access to the constructor in templates to prevent RCE

This commit fixes a Remote Code Execution (RCE) reported by
npm-security. Access to non-enumerable "constructor"-properties
is now prohibited by the compiled template-code, because this
the first step on the way to creating and execution arbitrary
JavaScript code.
The vulnerability affects systems where an attacker is allowed to
inject templates into the Handlebars setup.
Further details of the attack may be disclosed by npm-security.

Closes #1267
Closes #1495
This commit is contained in:
Nils Knappmeier
2019-01-30 22:21:44 +01:00
parent bacd473fe6
commit edc6220d51
2 changed files with 26 additions and 0 deletions
@@ -13,6 +13,9 @@ JavaScriptCompiler.prototype = {
// PUBLIC API: You can override these methods in a subclass to provide
// alternative compiled forms for name lookup and buffering semantics
nameLookup: function(parent, name/* , type*/) {
if (name === 'constructor') {
return ['(', parent, '.propertyIsEnumerable(\'constructor\') ? ', parent, '.constructor : undefined', ')'];
}
if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
return [parent, '.', name];
} else {
+23
View File
@@ -0,0 +1,23 @@
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}}', {}, '');
});
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');
});
it('should allow prototype properties that are not constructors', function() {
class TestClass {
get abc() {
return 'xyz';
}
}
shouldCompileTo('{{#with this as |obj|}}{{obj.abc}}{{/with}}',
new TestClass(), 'xyz');
});
});
});