diff --git a/.gitignore b/.gitignore index 3c6d099f..42b64dde 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ node_modules *.sublime-workspace npm-debug.log sauce_connect.log* +.idea +yarn-error.log diff --git a/Gruntfile.js b/Gruntfile.js index 25e1f1bd..be8e3ab0 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -183,7 +183,7 @@ module.exports = function(grunt) { grunt.task.loadTasks('tasks'); grunt.registerTask('bench', ['metrics']); - grunt.registerTask('sauce', process.env.SAUCE_USERNAME ? ['tests', 'connect', 'saucelabs-mocha'] : []); + grunt.registerTask('sauce', [] /* process.env.SAUCE_USERNAME ? ['tests', 'connect', 'saucelabs-mocha'] : [] */); grunt.registerTask('travis', process.env.PUBLISH ? ['default', 'sauce', 'metrics', 'publish:latest'] : ['default']); diff --git a/appveyor.yml b/appveyor.yml index b67fb4ca..563aaf93 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,8 +1,7 @@ # Test against these versions of Node.js environment: matrix: - - nodejs_version: "4" - - nodejs_version: "5" + - nodejs_version: "10" platform: - x64 diff --git a/lib/handlebars/base.js b/lib/handlebars/base.js index 127be4b7..22307b9d 100644 --- a/lib/handlebars/base.js +++ b/lib/handlebars/base.js @@ -4,7 +4,7 @@ import {registerDefaultHelpers} from './helpers'; import {registerDefaultDecorators} from './decorators'; import logger from './logger'; -export const VERSION = '4.0.12'; +export const VERSION = '4.1.0'; export const COMPILER_REVISION = 7; export const REVISION_CHANGES = { diff --git a/lib/handlebars/compiler/javascript-compiler.js b/lib/handlebars/compiler/javascript-compiler.js index 551ddbb2..d6ba5410 100644 --- a/lib/handlebars/compiler/javascript-compiler.js +++ b/lib/handlebars/compiler/javascript-compiler.js @@ -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 { diff --git a/package.json b/package.json index 6120b26a..7553b2cf 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "grunt-contrib-uglify": "^1", "grunt-contrib-watch": "^1.1.0", "grunt-eslint": "^20.1.0", - "grunt-saucelabs": "8.x", + "grunt-saucelabs": "9.x", "grunt-webpack": "^1.0.8", "istanbul": "kpdecker/istanbul", "jison": "0.4.16", diff --git a/release-notes.md b/release-notes.md index 782aace3..681bde43 100644 --- a/release-notes.md +++ b/release-notes.md @@ -2,7 +2,44 @@ ## Development -[Commits](https://github.com/wycats/handlebars.js/compare/v4.0.12...master) +[Commits](https://github.com/wycats/handlebars.js/compare/v4.1.0...master) + +## v4.1.0 - February 7th, 2019 +New Features + +- import TypeScript typings - 27ac1ee + +Security fixes: + +- disallow access to the constructor in templates to prevent RCE - 42841c4, #1495 + +Housekeeping + +- chore: fix components/handlebars package.json and auto-update on release - bacd473 +- chore: Use node 10 to build handlebars - 78dd89c +- chore/doc: Add more release docs - 6b87c21 + +Compatibility notes: + +Access to class constructors (i.e. `({}).constructor`) is now prohibited to prevent +Remote Code Execution. This means that following construct will no work anymore: + +``` +class SomeClass { +} + +SomeClass.staticProperty = 'static' + +var template = Handlebars.compile('{{constructor.staticProperty}}'); +document.getElementById('output').innerHTML = template(new SomeClass()); +// expected: 'static', but now this is empty. +``` + +This kind of access is not the intended use of Handlebars and leads to the vulnerability described in #1495. We will **not** increase the major version, because such use is not intended or documented, and because of the potential impact of the issue (we fear that most people won't use a new major version and the issue may not be resolved on many systems). + + + +[Commits](https://github.com/wycats/handlebars.js/compare/v4.0.12...v4.1.0) ## v4.0.12 - September 4th, 2018 New features: diff --git a/spec/security.js b/spec/security.js new file mode 100644 index 00000000..45b96c34 --- /dev/null +++ b/spec/security.js @@ -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'); + }); + }); +});