Skip to content

Commit

Permalink
Merge pull request #1 from mattolson/backport-rce-fix
Browse files Browse the repository at this point in the history
STRF-6929: Backport fixes to Handlebars 3.x
  • Loading branch information
mattolson committed Jun 29, 2019
2 parents 7cf753b + 322c2b3 commit 0277d62
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 7 deletions.
2 changes: 1 addition & 1 deletion components/bower.json
@@ -1,6 +1,6 @@
{
"name": "handlebars",
"version": "3.0.6",
"version": "3.1.0",
"main": "handlebars.js",
"dependencies": {}
}
2 changes: 1 addition & 1 deletion components/handlebars.js.nuspec
Expand Up @@ -2,7 +2,7 @@
<package>
<metadata>
<id>handlebars.js</id>
<version>3.0.6</version>
<version>3.1.0</version>
<authors>handlebars.js Authors</authors>
<licenseUrl>https://github.com/wycats/handlebars.js/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/wycats/handlebars.js/</projectUrl>
Expand Down
2 changes: 1 addition & 1 deletion components/package.json
@@ -1,6 +1,6 @@
{
"name": "handlebars",
"version": "3.0.6",
"version": "3.1.0",
"license": "MIT",
"jspm": {
"main": "handlebars",
Expand Down
8 changes: 7 additions & 1 deletion lib/handlebars/base.js
Expand Up @@ -212,7 +212,13 @@ function registerDefaultHelpers(instance) {
});

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];
});
}

Expand Down
3 changes: 3 additions & 0 deletions lib/handlebars/compiler/javascript-compiler.js
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion package.json
@@ -1,7 +1,7 @@
{
"name": "handlebars",
"barename": "handlebars",
"version": "3.0.6",
"version": "3.1.0",
"description": "Handlebars provides the power necessary to let you build semantic templates effectively with no frustration",
"homepage": "http://www.handlebarsjs.com/",
"keywords": [
Expand Down
27 changes: 26 additions & 1 deletion release-notes.md
Expand Up @@ -2,7 +2,32 @@

## Development

[Commits](https://github.com/wycats/handlebars.js/compare/v3.0.6...master)
[Commits](https://github.com/wycats/handlebars.js/compare/v3.1.0...master)

## v3.1.0 - June 28, 2019

Backport of security fixes from 4.1.0 and 4.1.2:

- disallow access to the constructor in templates to prevent RCE
- prevent RCE through the "lookup"-helper

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.
```

Similarly, access to the constructor of a class through {{lookup obj "constructor" }} is now prohibited.

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).

## v3.0.6 - January 2nd, 2019
Chore:
Expand Down
33 changes: 33 additions & 0 deletions spec/security.js
@@ -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');
});
});
});
2 changes: 1 addition & 1 deletion tasks/util/git.js
Expand Up @@ -86,7 +86,7 @@ module.exports = {
});
},
tagName: function(callback) {
childProcess.exec('git describe --tags', {}, function(err, stdout) {
childProcess.exec('git describe --tags --always', {}, function(err, stdout) {
if (err) {
throw new Error('git.tagName: ' + err.message);
}
Expand Down

0 comments on commit 0277d62

Please sign in to comment.