Bug#987042: buster-pu: package node-handlebars/4.1.0-1+deb10u3
Package: release.debian.org
Severity: normal
Tags: buster
User: release.debian.org@packages.debian.org
Usertags: pu
X-Debbugs-Cc: utkarsh@debian.org
[ Reason ]
node-handlebars is vulnerable to Arbitrary Code Execution and Remote
Code Execution (CVE-2019-20920 and CVE-2021-23369)
[ Impact ]
Medium vulnerabilities
[ Tests ]
Sadly there are no test launched in Buster even if upstream added some
checks
[ Risks ]
Medium risk, upstream patches were applied without changes
[ Checklist ]
[X] *all* changes are documented in the d/changelog
[X] I reviewed all changes and I approve them
[X] attach debdiff against the package in (old)stable
[X] the issue is verified as fixed in unstable
[ Changes ]
More checks for given arguments
Cheers,
Yadd
diff --git a/debian/changelog b/debian/changelog
index e49c409..e55d497 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+node-handlebars (3:4.1.0-1+deb10u3) buster; urgency=medium
+
+ * Team upload
+ * Fix arbitrary code execution (Closes: CVE-2019-20920)
+ * Fix remote code execution (Closes: CVE-2021-23369)
+
+ -- Yadd <yadd@debian.org> Fri, 16 Apr 2021 10:31:24 +0200
+
node-handlebars (3:4.1.0-1+deb10u2) buster; urgency=medium
* Fix regression introduced in 3:4.1.0-1+deb10u1
diff --git a/debian/patches/CVE-2019-20920.patch b/debian/patches/CVE-2019-20920.patch
new file mode 100644
index 0000000..54e3bd3
--- /dev/null
+++ b/debian/patches/CVE-2019-20920.patch
@@ -0,0 +1,114 @@
+Description: fix for CVE-2019-20920
+Author: Nils Knappmeier <github@knappi.org>
+Origin: upstream, https://github.com/handlebars-lang/handlebars.js/commit/1988878
+Bug: https://snyk.io/vuln/SNYK-JS-HANDLEBARS-534478
+Forwarded: not-needed
+Reviewed-By: Xavier Guimard <yadd@debian.org>
+Last-Update: 2020-10-12
+
+--- a/lib/handlebars/compiler/compiler.js
++++ b/lib/handlebars/compiler/compiler.js
+@@ -56,7 +56,7 @@
+
+ // These changes will propagate to the other compiler components
+ let knownHelpers = options.knownHelpers;
+- options.knownHelpers = {
++ options.knownHelpers = extend(Object.create(null), {
+ 'helperMissing': true,
+ 'blockHelperMissing': true,
+ 'each': true,
+@@ -65,15 +65,7 @@
+ 'with': true,
+ 'log': true,
+ 'lookup': true
+- };
+- if (knownHelpers) {
+- // the next line should use "Object.keys", but the code has been like this a long time and changing it, might
+- // cause backwards-compatibility issues... It's an old library...
+- // eslint-disable-next-line guard-for-in
+- for (let name in knownHelpers) {
+- this.options.knownHelpers[name] = knownHelpers[name];
+- }
+- }
++ }, options.knownHelpers);
+
+ return this.accept(program);
+ },
+--- a/lib/handlebars/compiler/javascript-compiler.js
++++ b/lib/handlebars/compiler/javascript-compiler.js
+@@ -2,6 +2,7 @@
+ import Exception from '../exception';
+ import {isArray} from '../utils';
+ import CodeGen from './code-gen';
++import {dangerousPropertyRegex} from '../helpers/lookup';
+
+ function Literal(value) {
+ this.value = value;
+@@ -13,8 +14,9 @@
+ // 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 (dangerousPropertyRegex.test(name)) {
++ const isEnumerable = [ this.aliasable('container.propertyIsEnumerable'), '.call(', parent, ',', JSON.stringify(name), ')'];
++ return ['(', isEnumerable, '?', _actualLookup(), ' : undefined)'];
+ }
+ if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
+ return [parent, '.', name];
+--- a/lib/handlebars/helpers/lookup.js
++++ b/lib/handlebars/helpers/lookup.js
+@@ -1,5 +1,13 @@
++export const dangerousPropertyRegex = /^(constructor|__defineGetter__|__defineSetter__|__lookupGetter__|__proto__)$/;
++
+ export default function(instance) {
+ instance.registerHelper('lookup', function(obj, field) {
+- return obj && obj[field];
++ if (!obj) {
++ return obj;
++ }
++ if (dangerousPropertyRegex.test(String(field)) && !obj.propertyIsEnumerable(field)) {
++ return undefined;
++ }
++ return obj[field];
+ });
+ }
+--- a/spec/security.js
++++ b/spec/security.js
+@@ -21,6 +21,36 @@
+ });
+ });
+
++ describe('GH-1563', function() {
++ it('should not allow to access constructor after overriding via __defineGetter__', function() {
++ if (({}).__defineGetter__ == null || ({}).__lookupGetter__ == null) {
++ return this.skip(); // Browser does not support this exploit anyway
++ }
++ expectTemplate('{{__defineGetter__ "undefined" valueOf }}' +
++ '{{#with __lookupGetter__ }}' +
++ '{{__defineGetter__ "propertyIsEnumerable" (this.bind (this.bind 1)) }}' +
++ '{{constructor.name}}' +
++ '{{/with}}')
++ .withInput({})
++ .toThrow(/Missing helper: "__defineGetter__"/);
++ });
++ });
++
++ describe('GH-1595', function() {
++ it('properties, that are required to be enumerable', function() {
++ expectTemplate('{{constructor}}').withInput({}).toCompileTo('');
++ expectTemplate('{{__defineGetter__}}').withInput({}).toCompileTo('');
++ expectTemplate('{{__defineSetter__}}').withInput({}).toCompileTo('');
++ expectTemplate('{{__lookupGetter__}}').withInput({}).toCompileTo('');
++ expectTemplate('{{__proto__}}').withInput({}).toCompileTo('');
++
++ expectTemplate('{{lookup "constructor"}}').withInput({}).toCompileTo('');
++ expectTemplate('{{lookup "__defineGetter__"}}').withInput({}).toCompileTo('');
++ expectTemplate('{{lookup "__defineSetter__"}}').withInput({}).toCompileTo('');
++ expectTemplate('{{lookup "__lookupGetter__"}}').withInput({}).toCompileTo('');
++ expectTemplate('{{lookup "__proto__"}}').withInput({}).toCompileTo('');
++ });
++ });
+ describe('GH-xxxx: Prevent explicit call of helperMissing-helpers', function() {
+ if (!Handlebars.compile) {
+ return;
diff --git a/debian/patches/CVE-2021-23369.patch b/debian/patches/CVE-2021-23369.patch
new file mode 100644
index 0000000..81ca9be
--- /dev/null
+++ b/debian/patches/CVE-2021-23369.patch
@@ -0,0 +1,38 @@
+Description: fix Remote Code Execution (RCE)
+ when selecting certain compiling options to compile templates coming from an
+ untrusted source.
+Author: Nils Knappmeier <npm@knappi.org>
+Origin: upstream, https://github.com/handlebars-lang/handlebars.js/commit/b6d3de71
+ https://github.com/handlebars-lang/handlebars.js/commit/f0589701
+Bug: https://snyk.io/vuln/SNYK-JS-HANDLEBARS-1056767
+Forwarded: not-needed
+Reviewed-By: Yadd <yadd@debian.org>
+Last-Update: 2021-04-16
+
+--- a/lib/handlebars/compiler/javascript-compiler.js
++++ b/lib/handlebars/compiler/javascript-compiler.js
+@@ -25,7 +25,12 @@
+ }
+ },
+ depthedLookup: function(name) {
+- return [this.aliasable('container.lookup'), '(depths, "', name, '")'];
++ return [
++ this.aliasable('container.lookup'),
++ '(depths, ',
++ JSON.stringify(name),
++ ')'
++ ];
+ },
+
+ compilerInfo: function() {
+--- a/lib/handlebars/runtime.js
++++ b/lib/handlebars/runtime.js
+@@ -78,7 +78,7 @@
+ if (!(name in obj)) {
+ throw new Exception('"' + name + '" not defined in ' + obj);
+ }
+- return obj[name];
++ return container.lookupProperty(obj, name);
+ },
+ lookup: function(depths, name) {
+ const len = depths.length;
diff --git a/debian/patches/series b/debian/patches/series
index 7cf0804..da74c64 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -2,3 +2,5 @@ port-to-babel6-webpack3.patch
skip-some-modules.patch
use-system-jison.patch
CVE-2019-19919.patch
+CVE-2019-20920.patch
+CVE-2021-23369.patch
Reply to: