fix: disallow the use of constructors in templates

This closes a major security leak that allows execution of arbitrary
code in a NodeJS environment by creating a special Handlebars template.
This commit is contained in:
Nils Knappmeier
2019-01-30 22:21:44 +01:00
parent bacd473fe6
commit d3e8e46095
3 changed files with 27 additions and 0 deletions
+2
View File
@@ -10,3 +10,5 @@ node_modules
*.sublime-workspace *.sublime-workspace
npm-debug.log npm-debug.log
sauce_connect.log* sauce_connect.log*
.idea
yarn-error.log
@@ -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 {
+22
View File
@@ -0,0 +1,22 @@
describe('security issues', function() {
it('should not allow constructors to be accessed', function() {
shouldCompileTo('{{#with this as |obj|}}{{obj.constructor.name}}{{/with}}', {}, '');
});
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');
});
});