diff --git a/components/bower.json b/components/bower.json
index fada3225e..53453c96d 100644
--- a/components/bower.json
+++ b/components/bower.json
@@ -1,6 +1,6 @@
 {
   "name": "handlebars",
-  "version": "4.5.1",
+  "version": "4.5.2",
   "main": "handlebars.js",
   "license": "MIT",
   "dependencies": {}
diff --git a/components/handlebars.js.nuspec b/components/handlebars.js.nuspec
index d7a2dffec..a4ec49b01 100644
--- a/components/handlebars.js.nuspec
+++ b/components/handlebars.js.nuspec
@@ -2,7 +2,7 @@
 <package>
 	<metadata>
 		<id>handlebars.js</id>
-		<version>4.5.1</version>
+		<version>4.5.2</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 a13ff027c..1fcee3eed 100644
--- a/components/package.json
+++ b/components/package.json
@@ -1,6 +1,6 @@
 {
   "name": "handlebars",
-  "version": "4.5.1",
+  "version": "4.5.2",
   "license": "MIT",
   "jspm": {
     "main": "handlebars",
diff --git a/lib/handlebars/base.js b/lib/handlebars/base.js
index fcf71a2b9..adb1547a5 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.5.1';
+export const VERSION = '4.5.2';
 export const COMPILER_REVISION = 8;
 export const LAST_COMPATIBLE_COMPILER_REVISION = 7;
 
diff --git a/lib/handlebars/helpers/lookup.js b/lib/handlebars/helpers/lookup.js
index dcd585178..0654cc393 100644
--- a/lib/handlebars/helpers/lookup.js
+++ b/lib/handlebars/helpers/lookup.js
@@ -3,7 +3,7 @@ export default function(instance) {
     if (!obj) {
       return obj;
     }
-    if (field === 'constructor' && !obj.propertyIsEnumerable(field)) {
+    if (String(field) === 'constructor' && !obj.propertyIsEnumerable(field)) {
       return undefined;
     }
     return obj[field];
diff --git a/package.json b/package.json
index 2cb199f32..d753c9b2a 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "handlebars",
   "barename": "handlebars",
-  "version": "4.5.1",
+  "version": "4.5.2",
   "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 11b1d0146..3eefabe89 100644
--- a/release-notes.md
+++ b/release-notes.md
@@ -2,7 +2,18 @@
 
 ## Development
 
-[Commits](https://github.com/wycats/handlebars.js/compare/v4.5.1...master)
+[Commits](https://github.com/wycats/handlebars.js/compare/v4.5.2...master)
+
+## v4.5.2 - November 13th, 2019
+# Bugfixes
+
+- fix: use String(field) in lookup when checking for "constructor" - d541378
+- test: add fluent API for testing Handlebars - c2ac79c
+
+Compatibility notes:
+- no incompatibility are to be expected
+
+[Commits](https://github.com/wycats/handlebars.js/compare/v4.5.1...v4.5.2)
 
 ## v4.5.1 - October 29th, 2019
 Bugfixs
diff --git a/spec/.eslintrc b/spec/.eslintrc
index 421bd00d2..34319f8c1 100644
--- a/spec/.eslintrc
+++ b/spec/.eslintrc
@@ -13,6 +13,7 @@
     "shouldCompileTo": true,
     "shouldCompileToWithPartials": true,
     "shouldThrow": true,
+    "expectTemplate": true,
     "compileWithPartials": true,
     "console": true,
     "require": true,
diff --git a/spec/env/common.js b/spec/env/common.js
index 14d302aa9..9523eaeb2 100644
--- a/spec/env/common.js
+++ b/spec/env/common.js
@@ -1,4 +1,6 @@
-var global = (function() { return this; }());
+var global = (function() {
+  return this;
+}());
 
 var AssertError;
 if (Error.captureStackTrace) {
@@ -16,10 +18,16 @@ if (Error.captureStackTrace) {
   AssertError = Error;
 }
 
+/**
+ * @deprecated Use "expectTemplate(template)...toCompileTo(output)" instead
+ */
 global.shouldCompileTo = function(string, hashOrArray, expected, message) {
   shouldCompileToWithPartials(string, hashOrArray, false, expected, message);
 };
 
+/**
+ * @deprecated Use "expectTemplate(template)...toCompileTo(output)" instead
+ */
 global.shouldCompileToWithPartials = function shouldCompileToWithPartials(string, hashOrArray, partials, expected, message) {
   var result = compileWithPartials(string, hashOrArray, partials);
   if (result !== expected) {
@@ -27,6 +35,9 @@ global.shouldCompileToWithPartials = function shouldCompileToWithPartials(string
   }
 };
 
+/**
+ * @deprecated Use "expectTemplate(template)...toCompileTo(output)" instead
+ */
 global.compileWithPartials = function(string, hashOrArray, partials) {
   var template,
       ary,
@@ -36,8 +47,8 @@ global.compileWithPartials = function(string, hashOrArray, partials) {
     delete hashOrArray.hash;
   } else if (Object.prototype.toString.call(hashOrArray) === '[object Array]') {
     ary = [];
-    ary.push(hashOrArray[0]);
-    ary.push({ helpers: hashOrArray[1], partials: hashOrArray[2] });
+    ary.push(hashOrArray[0]); // input
+    ary.push({helpers: hashOrArray[1], partials: hashOrArray[2]});
     options = typeof hashOrArray[3] === 'object' ? hashOrArray[3] : {compat: hashOrArray[3]};
     if (hashOrArray[4] != null) {
       options.data = !!hashOrArray[4];
@@ -75,3 +86,72 @@ global.shouldThrow = function(callback, type, msg) {
     throw new AssertError('It failed to throw', shouldThrow);
   }
 };
+
+
+global.expectTemplate = function(templateAsString) {
+  return new HandlebarsTestBench(templateAsString);
+};
+
+
+function HandlebarsTestBench(templateAsString) {
+  this.templateAsString = templateAsString;
+  this.helpers = {};
+  this.partials = {};
+  this.input = {};
+  this.message = 'Template' + templateAsString + ' does not evaluate to expected output';
+  this.compileOptions = {};
+  this.runtimeOptions = {};
+}
+
+HandlebarsTestBench.prototype.withInput = function(input) {
+  this.input = input;
+  return this;
+};
+
+HandlebarsTestBench.prototype.withHelper = function(name, helperFunction) {
+  this.helpers[name] = helperFunction;
+  return this;
+};
+
+HandlebarsTestBench.prototype.withPartial = function(name, partialAsString) {
+  this.partials[name] = partialAsString;
+  return this;
+};
+
+HandlebarsTestBench.prototype.withCompileOptions = function(compileOptions) {
+  this.compileOptions = compileOptions;
+  return this;
+};
+
+HandlebarsTestBench.prototype.withRuntimeOptions = function(runtimeOptions) {
+  this.runtimeOptions = runtimeOptions;
+  return this;
+};
+
+HandlebarsTestBench.prototype.withMessage = function(message) {
+  this.message = message;
+  return this;
+};
+
+HandlebarsTestBench.prototype.toCompileTo = function(expectedOutputAsString) {
+  var self = this;
+  var compile = Object.keys(this.partials).length > 0
+      ? CompilerContext.compileWithPartial
+      : CompilerContext.compile;
+
+  var combinedRuntimeOptions = {};
+  Object.keys(this.runtimeOptions).forEach(function(key) {
+    combinedRuntimeOptions[key] = self.runtimeOptions[key];
+  });
+  combinedRuntimeOptions.helpers = this.helpers;
+  combinedRuntimeOptions.partials = this.partials;
+
+  var template = compile(this.templateAsString, this.compileOptions);
+  var output = template(this.input, combinedRuntimeOptions);
+
+  if (output !== expectedOutputAsString) {
+    // Error message formatted so that IntelliJ-Idea shows "diff"-button
+    // https://stackoverflow.com/a/10945655/4251384
+    throw new AssertError(this.message + '\nexpected:' + expectedOutputAsString + 'but was:' + output);
+  }
+};
diff --git a/spec/security.js b/spec/security.js
index c50bda6d0..80b8e23c2 100644
--- a/spec/security.js
+++ b/spec/security.js
@@ -1,11 +1,26 @@
 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"}}', {}, '');
+            expectTemplate('{{lookup (lookup this "constructor") "name"}}')
+                .withInput({})
+                .toCompileTo('');
+
+            expectTemplate('{{constructor.name}}')
+                .withInput({})
+                .toCompileTo('');
         });
 
-        it('should allow the "constructor" property to be accessed if it is enumerable', function() {
+        it('GH-1603: should not allow constructors to be accessed (lookup via toString)', function() {
+          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 enumerable', function() {
             shouldCompileTo('{{constructor.name}}', {'constructor': {
                 'name': 'here we go'
             }}, 'here we go');
@@ -14,6 +29,13 @@ describe('security issues', function() {
             }}, 'here we go');
         });
 
+        it('should allow the "constructor" property to be accessed if it is enumerable', function() {
+            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() {
             }
