diff --git a/components/bower.json b/components/bower.json
index f590c5669..60e09e4d4 100644
--- a/components/bower.json
+++ b/components/bower.json
@@ -1,6 +1,6 @@
 {
   "name": "handlebars",
-  "version": "4.2.1",
+  "version": "4.3.0",
   "main": "handlebars.js",
   "license": "MIT",
   "dependencies": {}
diff --git a/components/handlebars.js.nuspec b/components/handlebars.js.nuspec
index 04c194afd..ff656b2ea 100644
--- a/components/handlebars.js.nuspec
+++ b/components/handlebars.js.nuspec
@@ -2,7 +2,7 @@
 <package>
 	<metadata>
 		<id>handlebars.js</id>
-		<version>4.2.1</version>
+		<version>4.3.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>
diff --git a/components/package.json b/components/package.json
index 8f1e063fb..a8cfd290a 100644
--- a/components/package.json
+++ b/components/package.json
@@ -1,6 +1,6 @@
 {
   "name": "handlebars",
-  "version": "4.2.1",
+  "version": "4.3.0",
   "license": "MIT",
   "jspm": {
     "main": "handlebars",
diff --git a/lib/handlebars/base.js b/lib/handlebars/base.js
index b0df08e0c..2703dafd6 100644
--- a/lib/handlebars/base.js
+++ b/lib/handlebars/base.js
@@ -4,8 +4,8 @@ import {registerDefaultHelpers} from './helpers';
 import {registerDefaultDecorators} from './decorators';
 import logger from './logger';
 
-export const VERSION = '4.2.1';
-export const COMPILER_REVISION = 7;
+export const VERSION = '4.3.0';
+export const COMPILER_REVISION = 8;
 
 export const REVISION_CHANGES = {
   1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
@@ -14,7 +14,8 @@ export const REVISION_CHANGES = {
   4: '== 1.x.x',
   5: '== 2.0.0-alpha.x',
   6: '>= 2.0.0-beta.1',
-  7: '>= 4.0.0'
+  7: '>= 4.0.0 <4.3.0',
+  8: '>= 4.3.0'
 };
 
 const objectType = '[object Object]';
diff --git a/lib/handlebars/compiler/javascript-compiler.js b/lib/handlebars/compiler/javascript-compiler.js
index ff98ad9e4..1b9b2318d 100644
--- a/lib/handlebars/compiler/javascript-compiler.js
+++ b/lib/handlebars/compiler/javascript-compiler.js
@@ -311,7 +311,7 @@ JavaScriptCompiler.prototype = {
   // replace it on the stack with the result of properly
   // invoking blockHelperMissing.
   blockValue: function(name) {
-    let blockHelperMissing = this.aliasable('helpers.blockHelperMissing'),
+    let blockHelperMissing = this.aliasable('container.hooks.blockHelperMissing'),
         params = [this.contextName(0)];
     this.setupHelperArgs(name, 0, params);
 
@@ -329,7 +329,7 @@ JavaScriptCompiler.prototype = {
   // On stack, after, if lastHelper: value
   ambiguousBlockValue: function() {
     // We're being a bit cheeky and reusing the options value from the prior exec
-    let blockHelperMissing = this.aliasable('helpers.blockHelperMissing'),
+    let blockHelperMissing = this.aliasable('container.hooks.blockHelperMissing'),
         params = [this.contextName(0)];
     this.setupHelperArgs('', 0, params, true);
 
@@ -622,18 +622,32 @@ JavaScriptCompiler.prototype = {
   // If the helper is not found, `helperMissing` is called.
   invokeHelper: function(paramSize, name, isSimple) {
     let nonHelper = this.popStack(),
-        helper = this.setupHelper(paramSize, name),
-        simple = isSimple ? [helper.name, ' || '] : '';
+        helper = this.setupHelper(paramSize, name);
 
-    let lookup = ['('].concat(simple, nonHelper);
+    let possibleFunctionCalls = [];
+
+    if (isSimple) { // direct call to helper
+      possibleFunctionCalls.push(helper.name);
+    }
+    // call a function from the input object
+    possibleFunctionCalls.push(nonHelper);
     if (!this.options.strict) {
-      lookup.push(' || ', this.aliasable('helpers.helperMissing'));
+      possibleFunctionCalls.push(this.aliasable('container.hooks.helperMissing'));
     }
-    lookup.push(')');
 
-    this.push(this.source.functionCall(lookup, 'call', helper.callParams));
+    let functionLookupCode = ['(', this.itemsSeparatedBy(possibleFunctionCalls, '||'), ')'];
+    let functionCall = this.source.functionCall(functionLookupCode, 'call', helper.callParams);
+    this.push(functionCall);
   },
 
+  itemsSeparatedBy: function(items, separator) {
+    let result = [];
+    result.push(items[0]);
+    for (let i = 1; i < items.length; i++) {
+      result.push(separator, items[i]);
+    }
+    return result;
+  },
   // [invokeKnownHelper]
   //
   // On stack, before: hash, inverse, program, params..., ...
@@ -673,7 +687,7 @@ JavaScriptCompiler.prototype = {
       lookup[0] = '(helper = ';
       lookup.push(
         ' != null ? helper : ',
-        this.aliasable('helpers.helperMissing')
+        this.aliasable('container.hooks.helperMissing')
       );
     }
 
diff --git a/lib/handlebars/helpers.js b/lib/handlebars/helpers.js
index 7a4365aea..804796820 100644
--- a/lib/handlebars/helpers.js
+++ b/lib/handlebars/helpers.js
@@ -15,3 +15,12 @@ export function registerDefaultHelpers(instance) {
   registerLookup(instance);
   registerWith(instance);
 }
+
+export function moveHelperToHooks(instance, helperName, keepHelper) {
+  if (instance.helpers[helperName]) {
+    instance.hooks[helperName] = instance.helpers[helperName];
+    if (!keepHelper) {
+      delete instance.helpers[helperName];
+    }
+  }
+}
diff --git a/lib/handlebars/runtime.js b/lib/handlebars/runtime.js
index a00f71e06..ce4630463 100644
--- a/lib/handlebars/runtime.js
+++ b/lib/handlebars/runtime.js
@@ -1,6 +1,7 @@
 import * as Utils from './utils';
 import Exception from './exception';
-import { COMPILER_REVISION, REVISION_CHANGES, createFrame } from './base';
+import {COMPILER_REVISION, createFrame, REVISION_CHANGES} from './base';
+import {moveHelperToHooks} from './helpers';
 
 export function checkRevision(compilerInfo) {
   const compilerRevision = compilerInfo && compilerInfo[0] || 1,
@@ -21,6 +22,7 @@ export function checkRevision(compilerInfo) {
 }
 
 export function template(templateSpec, env) {
+
   /* istanbul ignore next */
   if (!env) {
     throw new Exception('No environment passed to template');
@@ -42,13 +44,15 @@ export function template(templateSpec, env) {
         options.ids[0] = true;
       }
     }
-
     partial = env.VM.resolvePartial.call(this, partial, context, options);
-    let result = env.VM.invokePartial.call(this, partial, context, options);
+
+    let optionsWithHooks = Utils.extend({}, options, {hooks: this.hooks});
+
+    let result = env.VM.invokePartial.call(this, partial, context, optionsWithHooks);
 
     if (result == null && env.compile) {
       options.partials[options.name] = env.compile(partial, templateSpec.compilerOptions, env);
-      result = options.partials[options.name](context, options);
+      result = options.partials[options.name](context, optionsWithHooks);
     }
     if (result != null) {
       if (options.indent) {
@@ -115,15 +119,6 @@ export function template(templateSpec, env) {
       }
       return value;
     },
-    merge: function(param, common) {
-      let obj = param || common;
-
-      if (param && common && (param !== common)) {
-        obj = Utils.extend({}, common, param);
-      }
-
-      return obj;
-    },
     // An empty object to use as replacement for null-contexts
     nullContext: Object.seal({}),
 
@@ -158,19 +153,27 @@ export function template(templateSpec, env) {
 
   ret._setup = function(options) {
     if (!options.partial) {
-      container.helpers = container.merge(options.helpers, env.helpers);
+      container.helpers = Utils.extend({}, env.helpers, options.helpers);
 
       if (templateSpec.usePartial) {
-        container.partials = container.merge(options.partials, env.partials);
+        container.partials = Utils.extend({}, env.partials, options.partials);
       }
       if (templateSpec.usePartial || templateSpec.useDecorators) {
-        container.decorators = container.merge(options.decorators, env.decorators);
+        container.decorators = Utils.extend({}, env.decorators, options.decorators);
       }
+
+      container.hooks = {};
+      let keepHelper = options.allowCallsToHelperMissing;
+      moveHelperToHooks(container, 'helperMissing', keepHelper);
+      moveHelperToHooks(container, 'blockHelperMissing', keepHelper);
+
     } else {
       container.helpers = options.helpers;
       container.partials = options.partials;
       container.decorators = options.decorators;
+      container.hooks = options.hooks;
     }
+
   };
 
   ret._child = function(i, data, blockParams, depths) {
diff --git a/lib/handlebars/utils.js b/lib/handlebars/utils.js
index 2584601ef..8e1a4014f 100644
--- a/lib/handlebars/utils.js
+++ b/lib/handlebars/utils.js
@@ -1,3 +1,4 @@
+
 const escape = {
   '&': '&amp;',
   '<': '&lt;',
diff --git a/package.json b/package.json
index def528265..6b56332cb 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "handlebars",
   "barename": "handlebars",
-  "version": "4.2.1",
+  "version": "4.3.0",
   "description": "Handlebars provides the power necessary to let you build semantic templates effectively with no frustration",
   "homepage": "http://www.handlebarsjs.com/",
   "keywords": [
diff --git a/release-notes.md b/release-notes.md
index 48fc00146..8d11f07ba 100644
--- a/release-notes.md
+++ b/release-notes.md
@@ -2,7 +2,43 @@
 
 ## Development
 
-[Commits](https://github.com/wycats/handlebars.js/compare/v4.2.1...master)
+[Commits](https://github.com/wycats/handlebars.js/compare/v4.3.0...master)
+
+## v4.3.0 - September 24th, 2019
+Fixes:
+
+- Security: Disallow calling "helperMissing" and "blockHelperMissing" directly - 2078c72
+- Disallow calling "helperMissing" and "blockHelperMissing" directly - 2078c72
+
+Features:
+
+- Add new runtime option `allowCallsToHelperMissing` to allow calling `blockHelperMissing` and `helperMissing`.
+
+Breaking changes:
+
+Compatibility notes:
+- Compiler revision increased - 06b7224
+  - This means that template compiled with versions prior to 4.3.0 will not work with runtimes >= 4.3.0
+    The increase was done because the "helperMissing" and "blockHelperMissing" are now moved from the helpers
+    to the internal "container.hooks" object, so old templates will not be able to call them anymore. We suggest
+    that you always recompile your templates with the latest compiler in your build pipelines.
+
+- Disallow calling "helperMissing" and "blockHelperMissing" directly - 2078c72
+  - Calling "helperMissing" and "blockHelperMissing" directly from a template (like in `{{blockHelperMissing}}` was 
+    never intended and was part of the exploits that have been revealed early in 2019 
+    (see https://github.com/wycats/handlebars.js/issues/1495). *It is also part of a new exploit that 
+    is not captured by the earlier fix.* In order to harden Handlebars against such exploits, calling thos helpers 
+    is now not possible anymore. *Overriding* those helpers is still possible.
+  - If you really need this behavior, you can set the runtime option `allowCallsToHelperMissing` to `true` and the
+    calls will again be possible
+
+Both bullet points imly that Handlebars is not 100% percent compatible to 4.2.0, despite the minor version bump.
+
+We consider it more important to resolve a major security issue than to maintain 100% compatibility.
+
+    
+
+[Commits](https://github.com/wycats/handlebars.js/compare/v4.2.1...v4.3.0)
 
 ## v4.2.1 - September 20th, 2019
 Bugfixes: 
diff --git a/spec/expected/empty.amd.js b/spec/expected/empty.amd.js
index 1cf1eabc9..9728609ef 100644
--- a/spec/expected/empty.amd.js
+++ b/spec/expected/empty.amd.js
@@ -1,6 +1,6 @@
 define(['handlebars.runtime'], function(Handlebars) {
   Handlebars = Handlebars["default"];  var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
-return templates['empty'] = template({"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) {
+return templates['empty'] = template({"compiler":[8,">= 4.3.0"],"main":function(container,depth0,helpers,partials,data) {
     return "";
 },"useData":true});
 });
diff --git a/spec/security.js b/spec/security.js
index 4a7d83773..4c092b1c0 100644
--- a/spec/security.js
+++ b/spec/security.js
@@ -32,4 +32,60 @@ describe('security issues', function() {
 
         });
     });
+
+    describe('GH-xxxx: Prevent explicit call of helperMissing-helpers', function() {
+        if (!Handlebars.compile) {
+            return;
+        }
+
+        describe('without the option "allowExplicitCallOfHelperMissing"', function() {
+            it('should throw an exception when calling  "{{helperMissing}}" ', function() {
+                shouldThrow(function() {
+                    var template = Handlebars.compile('{{helperMissing}}');
+                    template({});
+                }, Error);
+            });
+            it('should throw an exception when calling  "{{#helperMissing}}{{/helperMissing}}" ', function() {
+                shouldThrow(function() {
+                    var template = Handlebars.compile('{{#helperMissing}}{{/helperMissing}}');
+                    template({});
+                }, Error);
+            });
+            it('should throw an exception when calling  "{{blockHelperMissing "abc" .}}" ', function() {
+                var functionCalls = [];
+                shouldThrow(function() {
+                    var template = Handlebars.compile('{{blockHelperMissing "abc" .}}');
+                    template({ fn: function() { functionCalls.push('called'); }});
+                }, Error);
+                equals(functionCalls.length, 0);
+            });
+            it('should throw an exception when calling  "{{#blockHelperMissing .}}{{/blockHelperMissing}}"', function() {
+                shouldThrow(function() {
+                    var template = Handlebars.compile('{{#blockHelperMissing .}}{{/blockHelperMissing}}');
+                    template({ fn: function() { return 'functionInData';}});
+                }, Error);
+            });
+        });
+
+        describe('with the option "allowCallsToHelperMissing" set to true', function() {
+            it('should not throw an exception when calling  "{{helperMissing}}" ', function() {
+                    var template = Handlebars.compile('{{helperMissing}}');
+                    template({}, {allowCallsToHelperMissing: true});
+            });
+            it('should not throw an exception when calling  "{{#helperMissing}}{{/helperMissing}}" ', function() {
+                    var template = Handlebars.compile('{{#helperMissing}}{{/helperMissing}}');
+                    template({}, {allowCallsToHelperMissing: true});
+            });
+            it('should not throw an exception when calling  "{{blockHelperMissing "abc" .}}" ', function() {
+                    var functionCalls = [];
+                    var template = Handlebars.compile('{{blockHelperMissing "abc" .}}');
+                    template({ fn: function() { functionCalls.push('called'); }}, {allowCallsToHelperMissing: true});
+                    equals(functionCalls.length, 1);
+            });
+            it('should not throw an exception when calling  "{{#blockHelperMissing .}}{{/blockHelperMissing}}"', function() {
+                    var template = Handlebars.compile('{{#blockHelperMissing true}}sdads{{/blockHelperMissing}}');
+                    template({}, {allowCallsToHelperMissing: true});
+            });
+        });
+    });
 });
diff --git a/types/index.d.ts b/types/index.d.ts
index a142119a4..bf8d17564 100644
--- a/types/index.d.ts
+++ b/types/index.d.ts
@@ -29,6 +29,7 @@ declare namespace Handlebars {
       decorators?: { [name: string]: Function };
       data?: any;
       blockParams?: any[];
+      allowCallsToHelperMissing: boolean;
   }
 
   export interface HelperOptions {
