aboutsummaryrefslogtreecommitdiff
path: root/dev/lib/handlebars/src/spec/index.security.test.ts
diff options
context:
space:
mode:
authorDarius Jahandarie <djahandarie@gmail.com>2023-11-09 13:30:31 +0000
committerGitHub <noreply@github.com>2023-11-09 13:30:31 +0000
commit5c5a167b4792af379cdacf633513cebf20728cd2 (patch)
tree5b6be3620a557d0b9177047003f6d742d9d2a32d /dev/lib/handlebars/src/spec/index.security.test.ts
parentb64f51c3b13a46af4dd7f1e43048ac19c781ca7b (diff)
parent0f4d36938fd0d844f548aa5a7f7e7842df8dfb41 (diff)
Merge pull request #307 from themoeway/modernize
Modernize codebase
Diffstat (limited to 'dev/lib/handlebars/src/spec/index.security.test.ts')
-rw-r--r--dev/lib/handlebars/src/spec/index.security.test.ts132
1 files changed, 132 insertions, 0 deletions
diff --git a/dev/lib/handlebars/src/spec/index.security.test.ts b/dev/lib/handlebars/src/spec/index.security.test.ts
new file mode 100644
index 00000000..878a0931
--- /dev/null
+++ b/dev/lib/handlebars/src/spec/index.security.test.ts
@@ -0,0 +1,132 @@
+/*
+ * This file is forked from the handlebars project (https://github.com/handlebars-lang/handlebars.js),
+ * and may include modifications made by Elasticsearch B.V.
+ * Elasticsearch B.V. licenses this file to you under the MIT License.
+ * See `packages/kbn-handlebars/LICENSE` for more information.
+ */
+
+import Handlebars from '../..';
+import { expectTemplate } from '../__jest__/test_bench';
+
+describe('security issues', () => {
+ describe('GH-1495: Prevent Remote Code Execution via constructor', () => {
+ it('should not allow constructors to be accessed', () => {
+ expectTemplate('{{lookup (lookup this "constructor") "name"}}').withInput({}).toCompileTo('');
+ expectTemplate('{{constructor.name}}').withInput({}).toCompileTo('');
+ });
+
+ it('GH-1603: should not allow constructors to be accessed (lookup via toString)', () => {
+ expectTemplate('{{lookup (lookup this (list "constructor")) "name"}}')
+ .withInput({})
+ .withHelper('list', function (element) {
+ return [element];
+ })
+ .toCompileTo('');
+ });
+
+ it('should allow the "constructor" property to be accessed if it is an "ownProperty"', () => {
+ expectTemplate('{{constructor.name}}')
+ .withInput({ constructor: { name: 'here we go' } })
+ .toCompileTo('here we go');
+
+ expectTemplate('{{lookup (lookup this "constructor") "name"}}')
+ .withInput({ constructor: { name: 'here we go' } })
+ .toCompileTo('here we go');
+ });
+
+ it('should allow the "constructor" property to be accessed if it is an "own property"', () => {
+ expectTemplate('{{lookup (lookup this "constructor") "name"}}')
+ .withInput({ constructor: { name: 'here we go' } })
+ .toCompileTo('here we go');
+ });
+ });
+
+ describe('GH-1558: Prevent explicit call of helperMissing-helpers', () => {
+ describe('without the option "allowExplicitCallOfHelperMissing"', () => {
+ it('should throw an exception when calling "{{helperMissing}}" ', () => {
+ expectTemplate('{{helperMissing}}').toThrow(Error);
+ });
+
+ it('should throw an exception when calling "{{#helperMissing}}{{/helperMissing}}" ', () => {
+ expectTemplate('{{#helperMissing}}{{/helperMissing}}').toThrow(Error);
+ });
+
+ it('should throw an exception when calling "{{blockHelperMissing "abc" .}}" ', () => {
+ const functionCalls = [];
+ expect(() => {
+ const template = Handlebars.compile('{{blockHelperMissing "abc" .}}');
+ template({
+ fn() {
+ functionCalls.push('called');
+ },
+ });
+ }).toThrow(Error);
+ expect(functionCalls.length).toEqual(0);
+ });
+
+ it('should throw an exception when calling "{{#blockHelperMissing .}}{{/blockHelperMissing}}"', () => {
+ expectTemplate('{{#blockHelperMissing .}}{{/blockHelperMissing}}')
+ .withInput({
+ fn() {
+ return 'functionInData';
+ },
+ })
+ .toThrow(Error);
+ });
+ });
+ });
+
+ describe('GH-1563', () => {
+ it('should not allow to access constructor after overriding via __defineGetter__', () => {
+ // @ts-expect-error
+ if ({}.__defineGetter__ == null || {}.__lookupGetter__ == null) {
+ return; // 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: dangerous properties', () => {
+ const templates = [
+ '{{constructor}}',
+ '{{__defineGetter__}}',
+ '{{__defineSetter__}}',
+ '{{__lookupGetter__}}',
+ '{{__proto__}}',
+ '{{lookup this "constructor"}}',
+ '{{lookup this "__defineGetter__"}}',
+ '{{lookup this "__defineSetter__"}}',
+ '{{lookup this "__lookupGetter__"}}',
+ '{{lookup this "__proto__"}}',
+ ];
+
+ templates.forEach((template) => {
+ describe('access should be denied to ' + template, () => {
+ it('by default', () => {
+ expectTemplate(template).withInput({}).toCompileTo('');
+ });
+ });
+ });
+ });
+
+ describe('escapes template variables', () => {
+ it('in default mode', () => {
+ expectTemplate("{{'a\\b'}}").withCompileOptions().withInput({ 'a\\b': 'c' }).toCompileTo('c');
+ });
+
+ it('in strict mode', () => {
+ expectTemplate("{{'a\\b'}}")
+ .withCompileOptions({ strict: true })
+ .withInput({ 'a\\b': 'c' })
+ .toCompileTo('c');
+ });
+ });
+});