CVE-2021-23624: Access of Resource Using Incompatible Type ('Type Confusion') (CWE-843)
value: This affects the package dotty before 0.1.2. A type confusion vulnerability can lead to a bypass of CVE-2021-25912 when the user-provided keys used in the path parameter are arrays.
CWE description: The product allocates or initializes a resource such as a pointer, object, or variable using one type, but it later accesses that resource using a type that is incompatible with the original type.
CVSS v3 base score: 9.8
Published: 2021-11-03T18:15Z
Repository: https://github.com/deoxxa/dotty
Language: JavaScript
Files changed: .github/workflows/main.yml, docs/docco.css, docs/lib/index.html, lib/index.js, package-lock.json, package.json, test/put-test.js, test/security-test.js
Commit date: 2021-10-26 10:46:00 -0500
Commit message: Address different method of prototype pollution (#32)

* remove ds_store file

* Fix pototype pollution

* Bump deps

* Update docs

* Update workflow to test against latest node versions

* Ensure put returns true

* Remove node v6,8,10 from testing
Diff: diff --git a/.DS_Store b/.DS_Store
deleted file mode 100644
index f277d81..0000000
Binary files a/.DS_Store and /dev/null differ
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index e01c5c2..42b822f 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -3,20 +3,19 @@ on:
   pull_request:
   push:
     branches:
       - main
       - master
-
 jobs:
   build:
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        node-version: [6.x, 8.x]
+        node-version: [10.x, 12.x, 14.x, 16.x]
     steps:
       - uses: actions/checkout@v2
       - name: Use Node.js ${{ matrix.node-version }}
-        uses: actions/setup-node@v1
+        uses: actions/setup-node@v2
         with:
           node-version: ${{ matrix.node-version }}
       - run: npm install
       - run: npm test
diff --git a/docs/docco.css b/docs/docco.css
index b60f6fa..c3d580f 100644
--- a/docs/docco.css
+++ b/docs/docco.css
@@ -211,11 +211,11 @@ ul.sections > li > div {
 #jump_page .source:first-child {
 }
 
 /*---------------------- Low resolutions (> 320px) ---------------------*/
 @media only screen and (min-width: 320px) {
-  .pilwrap { display: none; }
+  .sswrap { display: none; }
 
   ul.sections > li > div {
     display: block;
     padding:5px 10px 0 10px;
   }
@@ -328,33 +328,33 @@ ul.sections > li > div {
     border: none;
     -webkit-box-shadow: none;
     box-shadow: none;
   }
 
-  .pilwrap {
+  .sswrap {
     position: relative;
     display: inline;
   }
 
-  .pilcrow {
+  .ss {
     font: 12px Arial;
     text-decoration: none;
     color: #454545;
     position: absolute;
     top: 3px; left: -20px;
     padding: 1px 2px;
     opacity: 0;
     -webkit-transition: opacity 0.2s linear;
   }
-    .for-h1 .pilcrow {
+    .for-h1 .ss {
       top: 47px;
     }
-    .for-h2 .pilcrow, .for-h3 .pilcrow, .for-h4 .pilcrow {
+    .for-h2 .ss, .for-h3 .ss, .for-h4 .ss {
       top: 35px;
     }
 
-  ul.sections > li > div.annotation:hover .pilcrow {
+  ul.sections > li > div.annotation:hover .ss {
     opacity: 1;
   }
 }
 
 /*---------------------- (> 1025px) ---------------------*/
diff --git a/docs/lib/index.html b/docs/lib/index.html
index 519d056..cc12238 100644
--- a/docs/lib/index.html
+++ b/docs/lib/index.html
@@ -22,12 +22,12 @@
         
         
         <li id="section-1">
             <div class="annotation">
               
-              <div class="pilwrap ">
-                <a class="pilcrow" href="#section-1">&#182;</a>
+              <div class="sswrap ">
+                <a class="ss" href="#section-1">&#x00a7;</a>
               </div>
               <p>Dotty makes it easy to programmatically access arbitrarily nested objects and
 their properties.</p>
 
             </div>
@@ -36,54 +36,54 @@ their properties.</p>
         
         
         <li id="section-2">
             <div class="annotation">
               
-              <div class="pilwrap ">
-                <a class="pilcrow" href="#section-2">&#182;</a>
+              <div class="sswrap ">
+                <a class="ss" href="#section-2">&#x00a7;</a>
               </div>
               <p><code>object</code> is an object, <code>path</code> is the path to the property you want to check
 for existence of.</p>
 <p><code>path</code> can be provided as either a <code>&quot;string.separated.with.dots&quot;</code> or as
 <code>[&quot;an&quot;, &quot;array&quot;]</code>.</p>
 <p>Returns <code>true</code> if the path can be completely resolved, <code>false</code> otherwise.</p>
 
             </div>
             
             <div class="content"><div class='highlight'><pre>
-<span class="hljs-keyword">var</span> exists = (<span class="hljs-built_in">module</span>.exports.exists = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">exists</span>(<span class="hljs-params">object, path</span>) </span>{
-  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> path === <span class="hljs-string">"string"</span>) {
-    path = path.split(<span class="hljs-string">"."</span>);
+<span class="hljs-keyword">var</span> exists = (<span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span>.<span class="hljs-property">exists</span> = <span class="hljs-keyword">function</span> <span class="hljs-title function_">exists</span>(<span class="hljs-params">object, path</span>) {
+  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> path === <span class="hljs-string">&quot;string&quot;</span>) {
+    path = path.<span class="hljs-title function_">split</span>(<span class="hljs-string">&quot;.&quot;</span>);
   }
 
-  <span class="hljs-keyword">if</span> (!(path <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>) || path.length === <span class="hljs-number">0</span>) {
+  <span class="hljs-keyword">if</span> (!(path <span class="hljs-keyword">instanceof</span> <span class="hljs-title class_">Array</span>) || path.<span class="hljs-property">length</span> === <span class="hljs-number">0</span>) {
     <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
   }
 
-  path = path.slice();
+  path = path.<span class="hljs-title function_">slice</span>();
 
-  <span class="hljs-keyword">var</span> key = path.shift();
+  <span class="hljs-keyword">var</span> key = path.<span class="hljs-title function_">shift</span>();
 
-  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object !== <span class="hljs-string">"object"</span> || object === <span class="hljs-literal">null</span>) {
+  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object !== <span class="hljs-string">&quot;object&quot;</span> || object === <span class="hljs-literal">null</span>) {
     <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
   }
 
-  <span class="hljs-keyword">if</span> (path.length === <span class="hljs-number">0</span>) {
-    <span class="hljs-keyword">return</span> <span class="hljs-built_in">Object</span>.hasOwnProperty.apply(object, [key]);
+  <span class="hljs-keyword">if</span> (path.<span class="hljs-property">length</span> === <span class="hljs-number">0</span>) {
+    <span class="hljs-keyword">return</span> <span class="hljs-title class_">Object</span>.<span class="hljs-property">hasOwnProperty</span>.<span class="hljs-title function_">apply</span>(object, [key]);
   } <span class="hljs-keyword">else</span> {
-    <span class="hljs-keyword">return</span> exists(object[key], path);
+    <span class="hljs-keyword">return</span> <span class="hljs-title function_">exists</span>(object[key], path);
   }
 });</pre></div></div>
             
         </li>
         
         
         <li id="section-3">
             <div class="annotation">
               
-              <div class="pilwrap ">
-                <a class="pilcrow" href="#section-3">&#182;</a>
+              <div class="sswrap ">
+                <a class="ss" href="#section-3">&#x00a7;</a>
               </div>
               <p>These arguments are the same as those for <code>exists</code>.</p>
 <p>The return value, however, is the property you’re trying to access, or
 <code>undefined</code> if it can’t be found. This means you won’t be able to tell
 the difference between an unresolved path and an undefined property, so you
@@ -91,44 +91,44 @@ should not use <code>get</code> to check for the existence of a property. Use <c
 instead.</p>
 
             </div>
             
             <div class="content"><div class='highlight'><pre>
-<span class="hljs-keyword">var</span> get = (<span class="hljs-built_in">module</span>.exports.get = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">get</span>(<span class="hljs-params">object, path</span>) </span>{
-  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> path === <span class="hljs-string">"string"</span>) {
-    path = path.split(<span class="hljs-string">"."</span>);
+<span class="hljs-keyword">var</span> get = (<span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span>.<span class="hljs-property">get</span> = <span class="hljs-keyword">function</span> <span class="hljs-title function_">get</span>(<span class="hljs-params">object, path</span>) {
+  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> path === <span class="hljs-string">&quot;string&quot;</span>) {
+    path = path.<span class="hljs-title function_">split</span>(<span class="hljs-string">&quot;.&quot;</span>);
   }
 
-  <span class="hljs-keyword">if</span> (!(path <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>) || path.length === <span class="hljs-number">0</span>) {
+  <span class="hljs-keyword">if</span> (!(path <span class="hljs-keyword">instanceof</span> <span class="hljs-title class_">Array</span>) || path.<span class="hljs-property">length</span> === <span class="hljs-number">0</span>) {
     <span class="hljs-keyword">return</span>;
   }
 
-  path = path.slice();
+  path = path.<span class="hljs-title function_">slice</span>();
 
-  <span class="hljs-keyword">var</span> key = path.shift();
+  <span class="hljs-keyword">var</span> key = path.<span class="hljs-title function_">shift</span>();
 
-  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object !== <span class="hljs-string">"object"</span> || object === <span class="hljs-literal">null</span>) {
+  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object !== <span class="hljs-string">&quot;object&quot;</span> || object === <span class="hljs-literal">null</span>) {
     <span class="hljs-keyword">return</span>;
   }
 
-  <span class="hljs-keyword">if</span> (path.length === <span class="hljs-number">0</span>) {
+  <span class="hljs-keyword">if</span> (path.<span class="hljs-property">length</span> === <span class="hljs-number">0</span>) {
     <span class="hljs-keyword">return</span> object[key];
   }
 
-  <span class="hljs-keyword">if</span> (path.length) {
-    <span class="hljs-keyword">return</span> get(object[key], path);
+  <span class="hljs-keyword">if</span> (path.<span class="hljs-property">length</span>) {
+    <span class="hljs-keyword">return</span> <span class="hljs-title function_">get</span>(object[key], path);
   }
 });</pre></div></div>
             
         </li>
         
         
         <li id="section-4">
             <div class="annotation">
               
-              <div class="pilwrap ">
-                <a class="pilcrow" href="#section-4">&#182;</a>
+              <div class="sswrap ">
+                <a class="ss" href="#section-4">&#x00a7;</a>
               </div>
               <p>Arguments are similar to <code>exists</code> and <code>get</code>, with the exception that path
 components are regexes with some special cases. If a path component is <code>&quot;*&quot;</code>
 on its own, it’ll be converted to <code>/.*/</code>.</p>
 <p>The return value is an array of values where the key path matches the
@@ -137,52 +137,52 @@ specified criterion. If none match, an empty array will be returned.</p>
 match. Action params are value, parent and key.</p>
 
             </div>
             
             <div class="content"><div class='highlight'><pre>
-<span class="hljs-keyword">var</span> search = (<span class="hljs-built_in">module</span>.exports.search = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">search</span>(<span class="hljs-params">object, path, action</span>) </span>{
-  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> path === <span class="hljs-string">"string"</span>) {
-    path = path.split(<span class="hljs-string">"."</span>);
+<span class="hljs-keyword">var</span> search = (<span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span>.<span class="hljs-property">search</span> = <span class="hljs-keyword">function</span> <span class="hljs-title function_">search</span>(<span class="hljs-params">object, path, action</span>) {
+  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> path === <span class="hljs-string">&quot;string&quot;</span>) {
+    path = path.<span class="hljs-title function_">split</span>(<span class="hljs-string">&quot;.&quot;</span>);
   }
 
-  <span class="hljs-keyword">if</span> (!(path <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>) || path.length === <span class="hljs-number">0</span>) {
+  <span class="hljs-keyword">if</span> (!(path <span class="hljs-keyword">instanceof</span> <span class="hljs-title class_">Array</span>) || path.<span class="hljs-property">length</span> === <span class="hljs-number">0</span>) {
     <span class="hljs-keyword">return</span>;
   }
 
-  path = path.slice();
+  path = path.<span class="hljs-title function_">slice</span>();
 
-  <span class="hljs-keyword">var</span> key = path.shift();
+  <span class="hljs-keyword">var</span> key = path.<span class="hljs-title function_">shift</span>();
 
-  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object !== <span class="hljs-string">"object"</span> || object === <span class="hljs-literal">null</span>) {
+  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object !== <span class="hljs-string">&quot;object&quot;</span> || object === <span class="hljs-literal">null</span>) {
     <span class="hljs-keyword">return</span>;
   }
 
-  <span class="hljs-keyword">if</span> (key === <span class="hljs-string">"*"</span>) {
-    key = <span class="hljs-string">".*"</span>;
+  <span class="hljs-keyword">if</span> (key === <span class="hljs-string">&quot;*&quot;</span>) {
+    key = <span class="hljs-string">&quot;.*&quot;</span>;
   }
 
-  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> key === <span class="hljs-string">"string"</span>) {
-    key = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(key);
+  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> key === <span class="hljs-string">&quot;string&quot;</span>) {
+    key = <span class="hljs-keyword">new</span> <span class="hljs-title class_">RegExp</span>(key);
   }
 
-  <span class="hljs-keyword">if</span> (path.length === <span class="hljs-number">0</span>) {
-    <span class="hljs-keyword">return</span> <span class="hljs-built_in">Object</span>.keys(object)
-      .filter(key.test.bind(key))
-      .map(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">k</span>) </span>{
+  <span class="hljs-keyword">if</span> (path.<span class="hljs-property">length</span> === <span class="hljs-number">0</span>) {
+    <span class="hljs-keyword">return</span> <span class="hljs-title class_">Object</span>.<span class="hljs-title function_">keys</span>(object)
+      .<span class="hljs-title function_">filter</span>(key.<span class="hljs-property">test</span>.<span class="hljs-title function_">bind</span>(key))
+      .<span class="hljs-title function_">map</span>(<span class="hljs-keyword">function</span> (<span class="hljs-params">k</span>) {
         <span class="hljs-keyword">var</span> value = object[k];
         <span class="hljs-keyword">if</span> (action) {
-          action(value, object, k);
+          <span class="hljs-title function_">action</span>(value, object, k);
         }
         <span class="hljs-keyword">return</span> value;
       });
   } <span class="hljs-keyword">else</span> {
-    <span class="hljs-keyword">return</span> <span class="hljs-built_in">Array</span>.prototype.concat.apply(
+    <span class="hljs-keyword">return</span> <span class="hljs-title class_">Array</span>.<span class="hljs-property"><span class="hljs-keyword">prototype</span></span>.<span class="hljs-property">concat</span>.<span class="hljs-title function_">apply</span>(
       [],
-      <span class="hljs-built_in">Object</span>.keys(object)
-        .filter(key.test.bind(key))
-        .map(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">k</span>) </span>{
-          <span class="hljs-keyword">return</span> search(object[k], path, action);
+      <span class="hljs-title class_">Object</span>.<span class="hljs-title function_">keys</span>(object)
+        .<span class="hljs-title function_">filter</span>(key.<span class="hljs-property">test</span>.<span class="hljs-title function_">bind</span>(key))
+        .<span class="hljs-title function_">map</span>(<span class="hljs-keyword">function</span> (<span class="hljs-params">k</span>) {
+          <span class="hljs-keyword">return</span> <span class="hljs-title function_">search</span>(object[k], path, action);
         })
     );
   }
 });</pre></div></div>
             
@@ -190,24 +190,24 @@ match. Action params are value, parent and key.</p>
         
         
         <li id="section-5">
             <div class="annotation">
               
-              <div class="pilwrap ">
-                <a class="pilcrow" href="#section-5">&#182;</a>
+              <div class="sswrap ">
+                <a class="ss" href="#section-5">&#x00a7;</a>
               </div>
               <p>Perform a search and remove the matched keys.
 The return value is the same object argument with modifications.</p>
 
             </div>
             
             <div class="content"><div class='highlight'><pre>
-<span class="hljs-keyword">var</span> removeSearch = (<span class="hljs-built_in">module</span>.exports.removeSearch = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">removeSearch</span>(<span class="hljs-params">
+<span class="hljs-keyword">var</span> removeSearch = (<span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span>.<span class="hljs-property">removeSearch</span> = <span class="hljs-keyword">function</span> <span class="hljs-title function_">removeSearch</span>(<span class="hljs-params">
   object,
   path
-</span>) </span>{
-  search(object, path, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">value, object, key</span>) </span>{
+</span>) {
+  <span class="hljs-title function_">search</span>(object, path, <span class="hljs-keyword">function</span> (<span class="hljs-params">value, object, key</span>) {
     <span class="hljs-keyword">delete</span> object[key];
   });
   <span class="hljs-keyword">return</span> object;
 });</pre></div></div>
             
@@ -215,12 +215,12 @@ The return value is the same object argument with modifications.</p>
         
         
         <li id="section-6">
             <div class="annotation">
               
-              <div class="pilwrap ">
-                <a class="pilcrow" href="#section-6">&#182;</a>
+              <div class="sswrap ">
+                <a class="ss" href="#section-6">&#x00a7;</a>
               </div>
               <p>The first two arguments for <code>put</code> are the same as <code>exists</code> and <code>get</code>.</p>
 <p>The third argument is a value to <code>put</code> at the <code>path</code> of the <code>object</code>.
 Objects in the middle will be created if they don’t exist, or added to if
 they do. If a value is encountered in the middle of the path that is <em>not</em>
@@ -229,144 +229,144 @@ an object, it will not be overwritten.</p>
 successfully, or <code>false</code> otherwise.</p>
 
             </div>
             
             <div class="content"><div class='highlight'><pre>
-<span class="hljs-keyword">var</span> put = (<span class="hljs-built_in">module</span>.exports.put = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">put</span>(<span class="hljs-params">object, path, value</span>) </span>{
-  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> path === <span class="hljs-string">"string"</span>) {
-    path = path.split(<span class="hljs-string">"."</span>);
+<span class="hljs-keyword">var</span> put = (<span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span>.<span class="hljs-property">put</span> = <span class="hljs-keyword">function</span> <span class="hljs-title function_">put</span>(<span class="hljs-params">object, path, value</span>) {
+  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> path === <span class="hljs-string">&quot;string&quot;</span>) {
+    path = path.<span class="hljs-title function_">split</span>(<span class="hljs-string">&quot;.&quot;</span>);
   }
 
-  <span class="hljs-keyword">if</span> (!(path <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>) || path.length === <span class="hljs-number">0</span>) {
+  <span class="hljs-keyword">if</span> (!(path <span class="hljs-keyword">instanceof</span> <span class="hljs-title class_">Array</span>) || path.<span class="hljs-property">length</span> === <span class="hljs-number">0</span>) {
     <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
   }
 
-  path = path.slice();
+  path = path.<span class="hljs-title function_">slice</span>();
 
-  <span class="hljs-keyword">var</span> key = path.shift();
+  <span class="hljs-keyword">var</span> key = <span class="hljs-string">&quot;&quot;</span> + path.<span class="hljs-title function_">shift</span>();
 
-  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object !== <span class="hljs-string">"object"</span> || object === <span class="hljs-literal">null</span> || key === <span class="hljs-string">"__proto__"</span>) {
+  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object !== <span class="hljs-string">&quot;object&quot;</span> || object === <span class="hljs-literal">null</span> || key === <span class="hljs-string">&quot;__proto__&quot;</span>) {
     <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
   }
-  <span class="hljs-keyword">if</span> (path.length === <span class="hljs-number">0</span>) {
+  <span class="hljs-keyword">if</span> (path.<span class="hljs-property">length</span> === <span class="hljs-number">0</span>) {
     object[key] = value;
   } <span class="hljs-keyword">else</span> {
-    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object[key] === <span class="hljs-string">"undefined"</span>) {
+    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object[key] === <span class="hljs-string">&quot;undefined&quot;</span>) {
       object[key] = {};
     }
 
-    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object[key] !== <span class="hljs-string">"object"</span> || object[key] === <span class="hljs-literal">null</span>) {
+    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object[key] !== <span class="hljs-string">&quot;object&quot;</span> || object[key] === <span class="hljs-literal">null</span>) {
       <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
     }
 
-    <span class="hljs-keyword">return</span> put(object[key], path, value);
+    <span class="hljs-keyword">return</span> <span class="hljs-title function_">put</span>(object[key], path, value);
   }
 });</pre></div></div>
             
         </li>
         
         
         <li id="section-7">
             <div class="annotation">
               
-              <div class="pilwrap ">
-                <a class="pilcrow" href="#section-7">&#182;</a>
+              <div class="sswrap ">
+                <a class="ss" href="#section-7">&#x00a7;</a>
               </div>
               <p><code>remove</code> is like <code>put</code> in reverse!</p>
 <p>The return value is <code>true</code> in the case that the value existed and was removed
 successfully, or <code>false</code> otherwise.</p>
 
             </div>
             
             <div class="content"><div class='highlight'><pre>
-<span class="hljs-keyword">var</span> remove = (<span class="hljs-built_in">module</span>.exports.remove = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">remove</span>(<span class="hljs-params">object, path, value</span>) </span>{
-  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> path === <span class="hljs-string">"string"</span>) {
-    path = path.split(<span class="hljs-string">"."</span>);
+<span class="hljs-keyword">var</span> remove = (<span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span>.<span class="hljs-property">remove</span> = <span class="hljs-keyword">function</span> <span class="hljs-title function_">remove</span>(<span class="hljs-params">object, path, value</span>) {
+  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> path === <span class="hljs-string">&quot;string&quot;</span>) {
+    path = path.<span class="hljs-title function_">split</span>(<span class="hljs-string">&quot;.&quot;</span>);
   }
 
-  <span class="hljs-keyword">if</span> (!(path <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>) || path.length === <span class="hljs-number">0</span>) {
+  <span class="hljs-keyword">if</span> (!(path <span class="hljs-keyword">instanceof</span> <span class="hljs-title class_">Array</span>) || path.<span class="hljs-property">length</span> === <span class="hljs-number">0</span>) {
     <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
   }
 
-  path = path.slice();
+  path = path.<span class="hljs-title function_">slice</span>();
 
-  <span class="hljs-keyword">var</span> key = path.shift();
+  <span class="hljs-keyword">var</span> key = path.<span class="hljs-title function_">shift</span>();
 
-  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object !== <span class="hljs-string">"object"</span> || object === <span class="hljs-literal">null</span>) {
+  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object !== <span class="hljs-string">&quot;object&quot;</span> || object === <span class="hljs-literal">null</span>) {
     <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
   }
 
-  <span class="hljs-keyword">if</span> (path.length === <span class="hljs-number">0</span>) {
-    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">Object</span>.hasOwnProperty.call(object, key)) {
+  <span class="hljs-keyword">if</span> (path.<span class="hljs-property">length</span> === <span class="hljs-number">0</span>) {
+    <span class="hljs-keyword">if</span> (!<span class="hljs-title class_">Object</span>.<span class="hljs-property">hasOwnProperty</span>.<span class="hljs-title function_">call</span>(object, key)) {
       <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
     }
 
     <span class="hljs-keyword">delete</span> object[key];
 
     <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
   } <span class="hljs-keyword">else</span> {
-    <span class="hljs-keyword">return</span> remove(object[key], path, value);
+    <span class="hljs-keyword">return</span> <span class="hljs-title function_">remove</span>(object[key], path, value);
   }
 });</pre></div></div>
             
         </li>
         
         
         <li id="section-8">
             <div class="annotation">
               
-              <div class="pilwrap ">
-                <a class="pilcrow" href="#section-8">&#182;</a>
+              <div class="sswrap ">
+                <a class="ss" href="#section-8">&#x00a7;</a>
               </div>
               <p><code>deepKeys</code> creates a list of all possible key paths for a given object.</p>
 <p>The return value is always an array, the members of which are paths in array
 format. If you want them in dot-notation format, do something like this:</p>
-<pre><code class="lang-js">dotty.deepKeys(obj).map(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">e</span>) </span>{
-  <span class="hljs-keyword">return</span> e.join(<span class="hljs-string">"."</span>);
+<pre><code class="language-js">dotty.<span class="hljs-title function_">deepKeys</span>(obj).<span class="hljs-title function_">map</span>(<span class="hljs-keyword">function</span>(<span class="hljs-params">e</span>) {
+  <span class="hljs-keyword">return</span> e.<span class="hljs-title function_">join</span>(<span class="hljs-string">&quot;.&quot;</span>);
 });
 </code></pre>
 <p><em>Note: this will probably explode on recursive objects. Be careful.</em></p>
 
             </div>
             
             <div class="content"><div class='highlight'><pre>
-<span class="hljs-keyword">var</span> deepKeys = (<span class="hljs-built_in">module</span>.exports.deepKeys = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">deepKeys</span>(<span class="hljs-params">
+<span class="hljs-keyword">var</span> deepKeys = (<span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span>.<span class="hljs-property">deepKeys</span> = <span class="hljs-keyword">function</span> <span class="hljs-title function_">deepKeys</span>(<span class="hljs-params">
   object,
   options,
   prefix
-</span>) </span>{
+</span>) {
   options = options || {};
 
-  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> prefix === <span class="hljs-string">"undefined"</span>) {
+  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> prefix === <span class="hljs-string">&quot;undefined&quot;</span>) {
     prefix = [];
   }
 
   <span class="hljs-keyword">var</span> keys = [];
 
   <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> k <span class="hljs-keyword">in</span> object) {
-    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">Object</span>.hasOwnProperty.call(object, k)) {
+    <span class="hljs-keyword">if</span> (!<span class="hljs-title class_">Object</span>.<span class="hljs-property">hasOwnProperty</span>.<span class="hljs-title function_">call</span>(object, k)) {
       <span class="hljs-keyword">continue</span>;
     }
 
-    <span class="hljs-keyword">if</span> (!options.leavesOnly || <span class="hljs-keyword">typeof</span> object[k] !== <span class="hljs-string">"object"</span>) {
-      keys.push(prefix.concat([k]));
+    <span class="hljs-keyword">if</span> (!options.<span class="hljs-property">leavesOnly</span> || <span class="hljs-keyword">typeof</span> object[k] !== <span class="hljs-string">&quot;object&quot;</span>) {
+      keys.<span class="hljs-title function_">push</span>(prefix.<span class="hljs-title function_">concat</span>([k]));
     }
 
-    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object[k] === <span class="hljs-string">"object"</span> &amp;&amp; object[k] !== <span class="hljs-literal">null</span>) {
-      keys = keys.concat(
-        deepKeys(
+    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object[k] === <span class="hljs-string">&quot;object&quot;</span> &amp;&amp; object[k] !== <span class="hljs-literal">null</span>) {
+      keys = keys.<span class="hljs-title function_">concat</span>(
+        <span class="hljs-title function_">deepKeys</span>(
           object[k],
-          { <span class="hljs-attr">leavesOnly</span>: options.leavesOnly },
-          prefix.concat([k])
+          { <span class="hljs-attr">leavesOnly</span>: options.<span class="hljs-property">leavesOnly</span> },
+          prefix.<span class="hljs-title function_">concat</span>([k])
         )
       );
     }
   }
 
-  <span class="hljs-keyword">if</span> (options.asStrings) {
-    keys = keys.map(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">e</span>) </span>{
-      <span class="hljs-keyword">return</span> e.join(<span class="hljs-string">"."</span>);
+  <span class="hljs-keyword">if</span> (options.<span class="hljs-property">asStrings</span>) {
+    keys = keys.<span class="hljs-title function_">map</span>(<span class="hljs-keyword">function</span> (<span class="hljs-params">e</span>) {
+      <span class="hljs-keyword">return</span> e.<span class="hljs-title function_">join</span>(<span class="hljs-string">&quot;.&quot;</span>);
     });
   }
 
   <span class="hljs-keyword">return</span> keys;
 });</pre></div></div>
diff --git a/docs/public/fonts/roboto-black.eot b/docs/public/fonts/roboto-black.eot
old mode 100755
new mode 100644
diff --git a/docs/public/fonts/roboto-black.ttf b/docs/public/fonts/roboto-black.ttf
old mode 100755
new mode 100644
diff --git a/docs/public/fonts/roboto-black.woff b/docs/public/fonts/roboto-black.woff
old mode 100755
new mode 100644
diff --git a/lib/index.js b/lib/index.js
index c87cb22..14fb644 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -168,11 +168,11 @@ var put = (module.exports.put = function put(object, path, value) {
     return false;
   }
 
   path = path.slice();
 
-  var key = path.shift();
+  var key = "" + path.shift();
 
   if (typeof object !== "object" || object === null || key === "__proto__") {
     return false;
   }
   if (path.length === 0) {
@@ -186,10 +186,12 @@ var put = (module.exports.put = function put(object, path, value) {
       return false;
     }
 
     return put(object[key], path, value);
   }
+
+  return true;
 });
 
 //
 // `remove` is like `put` in reverse!
 //
diff --git a/package-lock.json b/package-lock.json
index b3c5923..8bed110 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2,26 +2,48 @@
   "name": "dotty",
   "version": "0.1.1",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
+    "balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+      "dev": true
+    },
+    "brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "requires": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
     "commander": {
-      "version": "2.14.1",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz",
-      "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw==",
+      "version": "8.3.0",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
+      "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
+      "dev": true
+    },
+    "concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
       "dev": true
     },
     "diff": {
-      "version": "1.0.8",
-      "resolved": "https://registry.npmjs.org/diff/-/diff-1.0.8.tgz",
-      "integrity": "sha1-NDJ2MI7Jkbe8giZ+1VvBQR+XFmY=",
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+      "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
       "dev": true
     },
     "docco": {
-      "version": "0.8.0",
-      "resolved": "https://registry.npmjs.org/docco/-/docco-0.8.0.tgz",
-      "integrity": "sha512-QcWBDnnGaT+rgC0wqynznXv0/4hd6nAFdWNs2fN4FvkH2yAnCYVeRU7GIZXNCeUQ955Lufq+TmZcSXiBa1cGQQ==",
+      "version": "0.8.1",
+      "resolved": "https://registry.npmjs.org/docco/-/docco-0.8.1.tgz",
+      "integrity": "sha512-OFVdjpxw4aTI+FThrCY2NEWZV/nvGDFlfeQxUTMkKL+oY2gD2sMl0N5ogoAj3YLZU05UDBSh64ROYzLFzxSoSQ==",
       "dev": true,
       "requires": {
         "commander": ">= 0.5.2",
         "fs-extra": ">= 0.6.0",
         "highlight.js": ">= 8.0.x",
@@ -34,134 +56,129 @@
       "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz",
       "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=",
       "dev": true
     },
     "fs-extra": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz",
-      "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==",
+      "version": "10.0.0",
+      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz",
+      "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==",
       "dev": true,
       "requires": {
-        "graceful-fs": "^4.1.2",
-        "jsonfile": "^4.0.0",
-        "universalify": "^0.1.0"
+        "graceful-fs": "^4.2.0",
+        "jsonfile": "^6.0.1",
+        "universalify": "^2.0.0"
       }
     },
+    "fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+      "dev": true
+    },
     "glob": {
-      "version": "4.0.6",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-4.0.6.tgz",
-      "integrity": "sha1-aVxQvdTi+1xdNwsJHziNNwfikac=",
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+      "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
       "dev": true,
       "requires": {
-        "graceful-fs": "^3.0.2",
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
         "inherits": "2",
-        "minimatch": "^1.0.0",
-        "once": "^1.3.0"
-      },
-      "dependencies": {
-        "graceful-fs": {
-          "version": "3.0.11",
-          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz",
-          "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=",
-          "dev": true,
-          "requires": {
-            "natives": "^1.1.0"
-          }
-        }
+        "minimatch": "^3.0.4",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
       }
     },
     "graceful-fs": {
-      "version": "4.1.11",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
-      "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
+      "version": "4.2.8",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz",
+      "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==",
       "dev": true
     },
     "highlight.js": {
-      "version": "10.5.0",
-      "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.5.0.tgz",
-      "integrity": "sha512-xTmvd9HiIHR6L53TMC7TKolEj65zG1XU+Onr8oi86mYa+nLcIbxTTWkpW7CsEwv/vK7u1zb8alZIMLDqqN6KTw==",
+      "version": "11.3.1",
+      "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.3.1.tgz",
+      "integrity": "sha512-PUhCRnPjLtiLHZAQ5A/Dt5F8cWZeMyj9KRsACsWT+OD6OP0x6dp5OmT5jdx0JgEyPxPZZIPQpRN2TciUT7occw==",
       "dev": true
     },
+    "inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+      "dev": true,
+      "requires": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
     "inherits": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
-      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
       "dev": true
     },
     "jsonfile": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
-      "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+      "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
       "dev": true,
       "requires": {
-        "graceful-fs": "^4.1.6"
+        "graceful-fs": "^4.1.6",
+        "universalify": "^2.0.0"
       }
     },
-    "lru-cache": {
-      "version": "2.7.3",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz",
-      "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=",
-      "dev": true
-    },
     "marked": {
-      "version": "1.2.7",
-      "resolved": "https://registry.npmjs.org/marked/-/marked-1.2.7.tgz",
-      "integrity": "sha512-No11hFYcXr/zkBvL6qFmAp1z6BKY3zqLMHny/JN/ey+al7qwCM2+CMBL9BOgqMxZU36fz4cCWfn2poWIf7QRXA==",
+      "version": "3.0.8",
+      "resolved": "https://registry.npmjs.org/marked/-/marked-3.0.8.tgz",
+      "integrity": "sha512-0gVrAjo5m0VZSJb4rpL59K1unJAMb/hm8HRXqasD8VeC8m91ytDPMritgFSlKonfdt+rRYYpP/JfLxgIX8yoSw==",
       "dev": true
     },
     "minimatch": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-1.0.0.tgz",
-      "integrity": "sha1-4N0hILSeG3JM6NcUxSCCKpQ4V20=",
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
       "dev": true,
       "requires": {
-        "lru-cache": "2",
-        "sigmund": "~1.0.0"
+        "brace-expansion": "^1.1.7"
       }
     },
-    "natives": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.1.tgz",
-      "integrity": "sha512-8eRaxn8u/4wN8tGkhlc2cgwwvOLMLUMUn4IYTexMgWd+LyUDfeXVkk2ygQR0hvIHbJQXgHujia3ieUUDwNGkEA==",
-      "dev": true
-    },
     "once": {
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
       "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
       "dev": true,
       "requires": {
         "wrappy": "1"
       }
     },
-    "sigmund": {
+    "path-is-absolute": {
       "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz",
-      "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=",
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
       "dev": true
     },
     "underscore": {
-      "version": "1.8.3",
-      "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
-      "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=",
+      "version": "1.13.1",
+      "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz",
+      "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==",
       "dev": true
     },
     "universalify": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz",
-      "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+      "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
       "dev": true
     },
     "vows": {
-      "version": "0.8.1",
-      "resolved": "https://registry.npmjs.org/vows/-/vows-0.8.1.tgz",
-      "integrity": "sha1-4J6YjOWUygWgjXKrzKNOiNtVkTE=",
+      "version": "0.8.3",
+      "resolved": "https://registry.npmjs.org/vows/-/vows-0.8.3.tgz",
+      "integrity": "sha512-PVIxa/ovXhrw5gA3mz6M+ZF3PHlqX4tutR2p/y9NWPAaFVKcWBE8b2ktfr0opQM/qFmcOVWKjSCJVjnYOvjXhw==",
       "dev": true,
       "requires": {
-        "diff": "~1.0.8",
+        "diff": "^4.0.1",
         "eyes": "~0.1.6",
-        "glob": "~4.0.6"
+        "glob": "^7.1.2"
       }
     },
     "wrappy": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
diff --git a/package.json b/package.json
index 43dcff9..70f9fc5 100644
--- a/package.json
+++ b/package.json
@@ -19,9 +19,9 @@
     "mongodb"
   ],
   "author": "Conrad Pankoff <deoxxa@fknsrs.biz> (http://www.fknsrs.biz/)",
   "license": "BSD-3-Clause",
   "devDependencies": {
-    "vows": "^0.8.0",
-    "docco": "^0.8.0"
+    "vows": "^0.8.3",
+    "docco": "^0.8.1"
   }
 }
diff --git a/test/put-test.js b/test/put-test.js
index d16f541..87b99b1 100644
--- a/test/put-test.js
+++ b/test/put-test.js
@@ -24,10 +24,19 @@ vows
         })(),
         "should set the correct value": function (res) {
           assert.equal(res.a, "b");
         },
       },
+      "returns true": {
+        topic: (function () {
+          var res = dotty.put({}, ["a"], "b");
+          return res;
+        })(),
+        "should set the correct value": function (res) {
+          assert.equal(res, true);
+        },
+      },
     },
     "A two-level path": {
       "as a string": {
         topic: (function () {
           var x = {};
diff --git a/test/security-test.js b/test/security-test.js
index 10a1670..f8a8936 100644
--- a/test/security-test.js
+++ b/test/security-test.js
@@ -1,25 +1,48 @@
-var dotty = require("../lib/index"),
+const dotty = require("../lib/index"),
   vows = require("vows"),
   assert = require("assert");
 
 vows
   .describe("security")
   .addBatch({
     "When we attempt to update the prototype": {
       topic() {
-        var obj = {};
+        const obj = {};
         dotty.put(obj, "__proto__.polluted", "Muhahahaha");
         return obj;
       },
       "it should not update": function (res) {
         assert.equal(res.polluted, undefined);
+        assert.equal(Object.prototype.polluted, undefined);
+      },
+    },
+    "When we attempt to update the prototype using an array": {
+      topic() {
+        const obj = {};
+        dotty.put(obj, ["__proto__", "polluted"], "Muhahahaha");
+        return obj;
+      },
+      "it should not update": function (res) {
+        assert.equal(res.polluted, undefined);
+        assert.equal(Object.prototype.polluted, undefined);
+      },
+    },
+    "When we attempt to update the prototype using a non-string": {
+      topic() {
+        const obj = {};
+        dotty.put(obj, [["__proto__"], "polluted"], "Muhahahaha");
+        return obj;
+      },
+      "it should not update": function (res) {
+        assert.equal(res.polluted, undefined);
+        assert.equal(Object.prototype.polluted, undefined);
       },
     },
     "When we attempt to update the constructor prototype": {
       topic() {
-        var obj = {};
+        const obj = {};
         dotty.put(obj, "constructor.prototype.polluted", "Muhahahaha");
         return obj;
       },
       "it should not update": function (res) {
         assert.equal(res.polluted, undefined);

Vulnerable code: 
        node-version: [6.x, 8.x]
        uses: actions/setup-node@v1
  .pilwrap { display: none; }
  .pilwrap {
  .pilcrow {
    .for-h1 .pilcrow {
    .for-h2 .pilcrow, .for-h3 .pilcrow, .for-h4 .pilcrow {
  ul.sections > li > div.annotation:hover .pilcrow {
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-1">&#182;</a>
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-2">&#182;</a>
<span class="hljs-keyword">var</span> exists = (<span class="hljs-built_in">module</span>.exports.exists = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">exists</span>(<span class="hljs-params">object, path</span>) </span>{
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> path === <span class="hljs-string">"string"</span>) {
    path = path.split(<span class="hljs-string">"."</span>);
  <span class="hljs-keyword">if</span> (!(path <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>) || path.length === <span class="hljs-number">0</span>) {
  path = path.slice();
  <span class="hljs-keyword">var</span> key = path.shift();
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object !== <span class="hljs-string">"object"</span> || object === <span class="hljs-literal">null</span>) {
  <span class="hljs-keyword">if</span> (path.length === <span class="hljs-number">0</span>) {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">Object</span>.hasOwnProperty.apply(object, [key]);
    <span class="hljs-keyword">return</span> exists(object[key], path);
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-3">&#182;</a>
<span class="hljs-keyword">var</span> get = (<span class="hljs-built_in">module</span>.exports.get = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">get</span>(<span class="hljs-params">object, path</span>) </span>{
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> path === <span class="hljs-string">"string"</span>) {
    path = path.split(<span class="hljs-string">"."</span>);
  <span class="hljs-keyword">if</span> (!(path <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>) || path.length === <span class="hljs-number">0</span>) {
  path = path.slice();
  <span class="hljs-keyword">var</span> key = path.shift();
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object !== <span class="hljs-string">"object"</span> || object === <span class="hljs-literal">null</span>) {
  <span class="hljs-keyword">if</span> (path.length === <span class="hljs-number">0</span>) {
  <span class="hljs-keyword">if</span> (path.length) {
    <span class="hljs-keyword">return</span> get(object[key], path);
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-4">&#182;</a>
<span class="hljs-keyword">var</span> search = (<span class="hljs-built_in">module</span>.exports.search = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">search</span>(<span class="hljs-params">object, path, action</span>) </span>{
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> path === <span class="hljs-string">"string"</span>) {
    path = path.split(<span class="hljs-string">"."</span>);
  <span class="hljs-keyword">if</span> (!(path <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>) || path.length === <span class="hljs-number">0</span>) {
  path = path.slice();
  <span class="hljs-keyword">var</span> key = path.shift();
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object !== <span class="hljs-string">"object"</span> || object === <span class="hljs-literal">null</span>) {
  <span class="hljs-keyword">if</span> (key === <span class="hljs-string">"*"</span>) {
    key = <span class="hljs-string">".*"</span>;
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> key === <span class="hljs-string">"string"</span>) {
    key = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(key);
  <span class="hljs-keyword">if</span> (path.length === <span class="hljs-number">0</span>) {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">Object</span>.keys(object)
      .filter(key.test.bind(key))
      .map(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">k</span>) </span>{
          action(value, object, k);
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">Array</span>.prototype.concat.apply(
      <span class="hljs-built_in">Object</span>.keys(object)
        .filter(key.test.bind(key))
        .map(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">k</span>) </span>{
          <span class="hljs-keyword">return</span> search(object[k], path, action);
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-5">&#182;</a>
<span class="hljs-keyword">var</span> removeSearch = (<span class="hljs-built_in">module</span>.exports.removeSearch = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">removeSearch</span>(<span class="hljs-params">
</span>) </span>{
  search(object, path, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">value, object, key</span>) </span>{
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-6">&#182;</a>
<span class="hljs-keyword">var</span> put = (<span class="hljs-built_in">module</span>.exports.put = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">put</span>(<span class="hljs-params">object, path, value</span>) </span>{
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> path === <span class="hljs-string">"string"</span>) {
    path = path.split(<span class="hljs-string">"."</span>);
  <span class="hljs-keyword">if</span> (!(path <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>) || path.length === <span class="hljs-number">0</span>) {
  path = path.slice();
  <span class="hljs-keyword">var</span> key = path.shift();
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object !== <span class="hljs-string">"object"</span> || object === <span class="hljs-literal">null</span> || key === <span class="hljs-string">"__proto__"</span>) {
  <span class="hljs-keyword">if</span> (path.length === <span class="hljs-number">0</span>) {
    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object[key] === <span class="hljs-string">"undefined"</span>) {
    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object[key] !== <span class="hljs-string">"object"</span> || object[key] === <span class="hljs-literal">null</span>) {
    <span class="hljs-keyword">return</span> put(object[key], path, value);
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-7">&#182;</a>
<span class="hljs-keyword">var</span> remove = (<span class="hljs-built_in">module</span>.exports.remove = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">remove</span>(<span class="hljs-params">object, path, value</span>) </span>{
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> path === <span class="hljs-string">"string"</span>) {
    path = path.split(<span class="hljs-string">"."</span>);
  <span class="hljs-keyword">if</span> (!(path <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>) || path.length === <span class="hljs-number">0</span>) {
  path = path.slice();
  <span class="hljs-keyword">var</span> key = path.shift();
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object !== <span class="hljs-string">"object"</span> || object === <span class="hljs-literal">null</span>) {
  <span class="hljs-keyword">if</span> (path.length === <span class="hljs-number">0</span>) {
    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">Object</span>.hasOwnProperty.call(object, key)) {
    <span class="hljs-keyword">return</span> remove(object[key], path, value);
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-8">&#182;</a>
<pre><code class="lang-js">dotty.deepKeys(obj).map(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">e</span>) </span>{
  <span class="hljs-keyword">return</span> e.join(<span class="hljs-string">"."</span>);
<span class="hljs-keyword">var</span> deepKeys = (<span class="hljs-built_in">module</span>.exports.deepKeys = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">deepKeys</span>(<span class="hljs-params">
</span>) </span>{
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> prefix === <span class="hljs-string">"undefined"</span>) {
    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">Object</span>.hasOwnProperty.call(object, k)) {
    <span class="hljs-keyword">if</span> (!options.leavesOnly || <span class="hljs-keyword">typeof</span> object[k] !== <span class="hljs-string">"object"</span>) {
      keys.push(prefix.concat([k]));
    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object[k] === <span class="hljs-string">"object"</span> &amp;&amp; object[k] !== <span class="hljs-literal">null</span>) {
      keys = keys.concat(
        deepKeys(
          { <span class="hljs-attr">leavesOnly</span>: options.leavesOnly },
          prefix.concat([k])
  <span class="hljs-keyword">if</span> (options.asStrings) {
    keys = keys.map(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">e</span>) </span>{
      <span class="hljs-keyword">return</span> e.join(<span class="hljs-string">"."</span>);
  var key = path.shift();
      "version": "2.14.1",
      "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz",
      "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw==",
      "version": "1.0.8",
      "resolved": "https://registry.npmjs.org/diff/-/diff-1.0.8.tgz",
      "integrity": "sha1-NDJ2MI7Jkbe8giZ+1VvBQR+XFmY=",
      "version": "0.8.0",
      "resolved": "https://registry.npmjs.org/docco/-/docco-0.8.0.tgz",
      "integrity": "sha512-QcWBDnnGaT+rgC0wqynznXv0/4hd6nAFdWNs2fN4FvkH2yAnCYVeRU7GIZXNCeUQ955Lufq+TmZcSXiBa1cGQQ==",
      "version": "5.0.0",
      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz",
      "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==",
        "graceful-fs": "^4.1.2",
        "jsonfile": "^4.0.0",
        "universalify": "^0.1.0"
      "version": "4.0.6",
      "resolved": "https://registry.npmjs.org/glob/-/glob-4.0.6.tgz",
      "integrity": "sha1-aVxQvdTi+1xdNwsJHziNNwfikac=",
        "graceful-fs": "^3.0.2",
        "minimatch": "^1.0.0",
        "once": "^1.3.0"
      },
      "dependencies": {
        "graceful-fs": {
          "version": "3.0.11",
          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz",
          "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=",
          "dev": true,
          "requires": {
            "natives": "^1.1.0"
          }
        }
      "version": "4.1.11",
      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
      "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
      "version": "10.5.0",
      "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.5.0.tgz",
      "integrity": "sha512-xTmvd9HiIHR6L53TMC7TKolEj65zG1XU+Onr8oi86mYa+nLcIbxTTWkpW7CsEwv/vK7u1zb8alZIMLDqqN6KTw==",
      "version": "2.0.3",
      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
      "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
        "graceful-fs": "^4.1.6"
    "lru-cache": {
      "version": "2.7.3",
      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz",
      "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=",
      "dev": true
    },
      "version": "1.2.7",
      "resolved": "https://registry.npmjs.org/marked/-/marked-1.2.7.tgz",
      "integrity": "sha512-No11hFYcXr/zkBvL6qFmAp1z6BKY3zqLMHny/JN/ey+al7qwCM2+CMBL9BOgqMxZU36fz4cCWfn2poWIf7QRXA==",
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-1.0.0.tgz",
      "integrity": "sha1-4N0hILSeG3JM6NcUxSCCKpQ4V20=",
        "lru-cache": "2",
        "sigmund": "~1.0.0"
    "natives": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.1.tgz",
      "integrity": "sha512-8eRaxn8u/4wN8tGkhlc2cgwwvOLMLUMUn4IYTexMgWd+LyUDfeXVkk2ygQR0hvIHbJQXgHujia3ieUUDwNGkEA==",
      "dev": true
    },
    "sigmund": {
      "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz",
      "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=",
      "version": "1.8.3",
      "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
      "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=",
      "version": "0.1.1",
      "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz",
      "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=",
      "version": "0.8.1",
      "resolved": "https://registry.npmjs.org/vows/-/vows-0.8.1.tgz",
      "integrity": "sha1-4J6YjOWUygWgjXKrzKNOiNtVkTE=",
        "diff": "~1.0.8",
        "glob": "~4.0.6"
    "vows": "^0.8.0",
    "docco": "^0.8.0"
var dotty = require("../lib/index"),
        var obj = {};
        var obj = {};
Fixed code:         node-version: [10.x, 12.x, 14.x, 16.x]
        uses: actions/setup-node@v2
  .sswrap { display: none; }
  .sswrap {
  .ss {
    .for-h1 .ss {
    .for-h2 .ss, .for-h3 .ss, .for-h4 .ss {
  ul.sections > li > div.annotation:hover .ss {
              <div class="sswrap ">
                <a class="ss" href="#section-1">&#x00a7;</a>
              <div class="sswrap ">
                <a class="ss" href="#section-2">&#x00a7;</a>
<span class="hljs-keyword">var</span> exists = (<span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span>.<span class="hljs-property">exists</span> = <span class="hljs-keyword">function</span> <span class="hljs-title function_">exists</span>(<span class="hljs-params">object, path</span>) {
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> path === <span class="hljs-string">&quot;string&quot;</span>) {
    path = path.<span class="hljs-title function_">split</span>(<span class="hljs-string">&quot;.&quot;</span>);
  <span class="hljs-keyword">if</span> (!(path <span class="hljs-keyword">instanceof</span> <span class="hljs-title class_">Array</span>) || path.<span class="hljs-property">length</span> === <span class="hljs-number">0</span>) {
  path = path.<span class="hljs-title function_">slice</span>();
  <span class="hljs-keyword">var</span> key = path.<span class="hljs-title function_">shift</span>();
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object !== <span class="hljs-string">&quot;object&quot;</span> || object === <span class="hljs-literal">null</span>) {
  <span class="hljs-keyword">if</span> (path.<span class="hljs-property">length</span> === <span class="hljs-number">0</span>) {
    <span class="hljs-keyword">return</span> <span class="hljs-title class_">Object</span>.<span class="hljs-property">hasOwnProperty</span>.<span class="hljs-title function_">apply</span>(object, [key]);
    <span class="hljs-keyword">return</span> <span class="hljs-title function_">exists</span>(object[key], path);
              <div class="sswrap ">
                <a class="ss" href="#section-3">&#x00a7;</a>
<span class="hljs-keyword">var</span> get = (<span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span>.<span class="hljs-property">get</span> = <span class="hljs-keyword">function</span> <span class="hljs-title function_">get</span>(<span class="hljs-params">object, path</span>) {
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> path === <span class="hljs-string">&quot;string&quot;</span>) {
    path = path.<span class="hljs-title function_">split</span>(<span class="hljs-string">&quot;.&quot;</span>);
  <span class="hljs-keyword">if</span> (!(path <span class="hljs-keyword">instanceof</span> <span class="hljs-title class_">Array</span>) || path.<span class="hljs-property">length</span> === <span class="hljs-number">0</span>) {
  path = path.<span class="hljs-title function_">slice</span>();
  <span class="hljs-keyword">var</span> key = path.<span class="hljs-title function_">shift</span>();
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object !== <span class="hljs-string">&quot;object&quot;</span> || object === <span class="hljs-literal">null</span>) {
  <span class="hljs-keyword">if</span> (path.<span class="hljs-property">length</span> === <span class="hljs-number">0</span>) {
  <span class="hljs-keyword">if</span> (path.<span class="hljs-property">length</span>) {
    <span class="hljs-keyword">return</span> <span class="hljs-title function_">get</span>(object[key], path);
              <div class="sswrap ">
                <a class="ss" href="#section-4">&#x00a7;</a>
<span class="hljs-keyword">var</span> search = (<span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span>.<span class="hljs-property">search</span> = <span class="hljs-keyword">function</span> <span class="hljs-title function_">search</span>(<span class="hljs-params">object, path, action</span>) {
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> path === <span class="hljs-string">&quot;string&quot;</span>) {
    path = path.<span class="hljs-title function_">split</span>(<span class="hljs-string">&quot;.&quot;</span>);
  <span class="hljs-keyword">if</span> (!(path <span class="hljs-keyword">instanceof</span> <span class="hljs-title class_">Array</span>) || path.<span class="hljs-property">length</span> === <span class="hljs-number">0</span>) {
  path = path.<span class="hljs-title function_">slice</span>();
  <span class="hljs-keyword">var</span> key = path.<span class="hljs-title function_">shift</span>();
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object !== <span class="hljs-string">&quot;object&quot;</span> || object === <span class="hljs-literal">null</span>) {
  <span class="hljs-keyword">if</span> (key === <span class="hljs-string">&quot;*&quot;</span>) {
    key = <span class="hljs-string">&quot;.*&quot;</span>;
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> key === <span class="hljs-string">&quot;string&quot;</span>) {
    key = <span class="hljs-keyword">new</span> <span class="hljs-title class_">RegExp</span>(key);
  <span class="hljs-keyword">if</span> (path.<span class="hljs-property">length</span> === <span class="hljs-number">0</span>) {
    <span class="hljs-keyword">return</span> <span class="hljs-title class_">Object</span>.<span class="hljs-title function_">keys</span>(object)
      .<span class="hljs-title function_">filter</span>(key.<span class="hljs-property">test</span>.<span class="hljs-title function_">bind</span>(key))
      .<span class="hljs-title function_">map</span>(<span class="hljs-keyword">function</span> (<span class="hljs-params">k</span>) {
          <span class="hljs-title function_">action</span>(value, object, k);
    <span class="hljs-keyword">return</span> <span class="hljs-title class_">Array</span>.<span class="hljs-property"><span class="hljs-keyword">prototype</span></span>.<span class="hljs-property">concat</span>.<span class="hljs-title function_">apply</span>(
      <span class="hljs-title class_">Object</span>.<span class="hljs-title function_">keys</span>(object)
        .<span class="hljs-title function_">filter</span>(key.<span class="hljs-property">test</span>.<span class="hljs-title function_">bind</span>(key))
        .<span class="hljs-title function_">map</span>(<span class="hljs-keyword">function</span> (<span class="hljs-params">k</span>) {
          <span class="hljs-keyword">return</span> <span class="hljs-title function_">search</span>(object[k], path, action);
              <div class="sswrap ">
                <a class="ss" href="#section-5">&#x00a7;</a>
<span class="hljs-keyword">var</span> removeSearch = (<span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span>.<span class="hljs-property">removeSearch</span> = <span class="hljs-keyword">function</span> <span class="hljs-title function_">removeSearch</span>(<span class="hljs-params">
</span>) {
  <span class="hljs-title function_">search</span>(object, path, <span class="hljs-keyword">function</span> (<span class="hljs-params">value, object, key</span>) {
              <div class="sswrap ">
                <a class="ss" href="#section-6">&#x00a7;</a>
<span class="hljs-keyword">var</span> put = (<span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span>.<span class="hljs-property">put</span> = <span class="hljs-keyword">function</span> <span class="hljs-title function_">put</span>(<span class="hljs-params">object, path, value</span>) {
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> path === <span class="hljs-string">&quot;string&quot;</span>) {
    path = path.<span class="hljs-title function_">split</span>(<span class="hljs-string">&quot;.&quot;</span>);
  <span class="hljs-keyword">if</span> (!(path <span class="hljs-keyword">instanceof</span> <span class="hljs-title class_">Array</span>) || path.<span class="hljs-property">length</span> === <span class="hljs-number">0</span>) {
  path = path.<span class="hljs-title function_">slice</span>();
  <span class="hljs-keyword">var</span> key = <span class="hljs-string">&quot;&quot;</span> + path.<span class="hljs-title function_">shift</span>();
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object !== <span class="hljs-string">&quot;object&quot;</span> || object === <span class="hljs-literal">null</span> || key === <span class="hljs-string">&quot;__proto__&quot;</span>) {
  <span class="hljs-keyword">if</span> (path.<span class="hljs-property">length</span> === <span class="hljs-number">0</span>) {
    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object[key] === <span class="hljs-string">&quot;undefined&quot;</span>) {
    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object[key] !== <span class="hljs-string">&quot;object&quot;</span> || object[key] === <span class="hljs-literal">null</span>) {
    <span class="hljs-keyword">return</span> <span class="hljs-title function_">put</span>(object[key], path, value);
              <div class="sswrap ">
                <a class="ss" href="#section-7">&#x00a7;</a>
<span class="hljs-keyword">var</span> remove = (<span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span>.<span class="hljs-property">remove</span> = <span class="hljs-keyword">function</span> <span class="hljs-title function_">remove</span>(<span class="hljs-params">object, path, value</span>) {
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> path === <span class="hljs-string">&quot;string&quot;</span>) {
    path = path.<span class="hljs-title function_">split</span>(<span class="hljs-string">&quot;.&quot;</span>);
  <span class="hljs-keyword">if</span> (!(path <span class="hljs-keyword">instanceof</span> <span class="hljs-title class_">Array</span>) || path.<span class="hljs-property">length</span> === <span class="hljs-number">0</span>) {
  path = path.<span class="hljs-title function_">slice</span>();
  <span class="hljs-keyword">var</span> key = path.<span class="hljs-title function_">shift</span>();
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object !== <span class="hljs-string">&quot;object&quot;</span> || object === <span class="hljs-literal">null</span>) {
  <span class="hljs-keyword">if</span> (path.<span class="hljs-property">length</span> === <span class="hljs-number">0</span>) {
    <span class="hljs-keyword">if</span> (!<span class="hljs-title class_">Object</span>.<span class="hljs-property">hasOwnProperty</span>.<span class="hljs-title function_">call</span>(object, key)) {
    <span class="hljs-keyword">return</span> <span class="hljs-title function_">remove</span>(object[key], path, value);
              <div class="sswrap ">
                <a class="ss" href="#section-8">&#x00a7;</a>
<pre><code class="language-js">dotty.<span class="hljs-title function_">deepKeys</span>(obj).<span class="hljs-title function_">map</span>(<span class="hljs-keyword">function</span>(<span class="hljs-params">e</span>) {
  <span class="hljs-keyword">return</span> e.<span class="hljs-title function_">join</span>(<span class="hljs-string">&quot;.&quot;</span>);
<span class="hljs-keyword">var</span> deepKeys = (<span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span>.<span class="hljs-property">deepKeys</span> = <span class="hljs-keyword">function</span> <span class="hljs-title function_">deepKeys</span>(<span class="hljs-params">
</span>) {
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> prefix === <span class="hljs-string">&quot;undefined&quot;</span>) {
    <span class="hljs-keyword">if</span> (!<span class="hljs-title class_">Object</span>.<span class="hljs-property">hasOwnProperty</span>.<span class="hljs-title function_">call</span>(object, k)) {
    <span class="hljs-keyword">if</span> (!options.<span class="hljs-property">leavesOnly</span> || <span class="hljs-keyword">typeof</span> object[k] !== <span class="hljs-string">&quot;object&quot;</span>) {
      keys.<span class="hljs-title function_">push</span>(prefix.<span class="hljs-title function_">concat</span>([k]));
    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object[k] === <span class="hljs-string">&quot;object&quot;</span> &amp;&amp; object[k] !== <span class="hljs-literal">null</span>) {
      keys = keys.<span class="hljs-title function_">concat</span>(
        <span class="hljs-title function_">deepKeys</span>(
          { <span class="hljs-attr">leavesOnly</span>: options.<span class="hljs-property">leavesOnly</span> },
          prefix.<span class="hljs-title function_">concat</span>([k])
  <span class="hljs-keyword">if</span> (options.<span class="hljs-property">asStrings</span>) {
    keys = keys.<span class="hljs-title function_">map</span>(<span class="hljs-keyword">function</span> (<span class="hljs-params">e</span>) {
      <span class="hljs-keyword">return</span> e.<span class="hljs-title function_">join</span>(<span class="hljs-string">&quot;.&quot;</span>);
  var key = "" + path.shift();

  return true;
    "balanced-match": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
      "dev": true
    },
    "brace-expansion": {
      "version": "1.1.11",
      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
      "dev": true,
      "requires": {
        "balanced-match": "^1.0.0",
        "concat-map": "0.0.1"
      }
    },
      "version": "8.3.0",
      "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
      "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
      "dev": true
    },
    "concat-map": {
      "version": "0.0.1",
      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
      "version": "4.0.2",
      "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
      "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
      "version": "0.8.1",
      "resolved": "https://registry.npmjs.org/docco/-/docco-0.8.1.tgz",
      "integrity": "sha512-OFVdjpxw4aTI+FThrCY2NEWZV/nvGDFlfeQxUTMkKL+oY2gD2sMl0N5ogoAj3YLZU05UDBSh64ROYzLFzxSoSQ==",
      "version": "10.0.0",
      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz",
      "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==",
        "graceful-fs": "^4.2.0",
        "jsonfile": "^6.0.1",
        "universalify": "^2.0.0"
    "fs.realpath": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
      "dev": true
    },
      "version": "7.2.0",
      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
      "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
        "fs.realpath": "^1.0.0",
        "inflight": "^1.0.4",
        "minimatch": "^3.0.4",
        "once": "^1.3.0",
        "path-is-absolute": "^1.0.0"
      "version": "4.2.8",
      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz",
      "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==",
      "version": "11.3.1",
      "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.3.1.tgz",
      "integrity": "sha512-PUhCRnPjLtiLHZAQ5A/Dt5F8cWZeMyj9KRsACsWT+OD6OP0x6dp5OmT5jdx0JgEyPxPZZIPQpRN2TciUT7occw==",
    "inflight": {
      "version": "1.0.6",
      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
      "dev": true,
      "requires": {
        "once": "^1.3.0",
        "wrappy": "1"
      }
    },
      "version": "2.0.4",
      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
      "version": "6.1.0",
      "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
      "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
        "graceful-fs": "^4.1.6",
        "universalify": "^2.0.0"
      "version": "3.0.8",
      "resolved": "https://registry.npmjs.org/marked/-/marked-3.0.8.tgz",
      "integrity": "sha512-0gVrAjo5m0VZSJb4rpL59K1unJAMb/hm8HRXqasD8VeC8m91ytDPMritgFSlKonfdt+rRYYpP/JfLxgIX8yoSw==",
      "version": "3.0.4",
      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
        "brace-expansion": "^1.1.7"
    "path-is-absolute": {
      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
      "version": "1.13.1",
      "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz",
      "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==",
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
      "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
      "version": "0.8.3",
      "resolved": "https://registry.npmjs.org/vows/-/vows-0.8.3.tgz",
      "integrity": "sha512-PVIxa/ovXhrw5gA3mz6M+ZF3PHlqX4tutR2p/y9NWPAaFVKcWBE8b2ktfr0opQM/qFmcOVWKjSCJVjnYOvjXhw==",
        "diff": "^4.0.1",
        "glob": "^7.1.2"
    "vows": "^0.8.3",
    "docco": "^0.8.1"
      "returns true": {
        topic: (function () {
          var res = dotty.put({}, ["a"], "b");
          return res;
        })(),
        "should set the correct value": function (res) {
          assert.equal(res, true);
        },
      },
const dotty = require("../lib/index"),
        const obj = {};
        assert.equal(Object.prototype.polluted, undefined);
      },
    },
    "When we attempt to update the prototype using an array": {
      topic() {
        const obj = {};
        dotty.put(obj, ["__proto__", "polluted"], "Muhahahaha");
        return obj;
      },
      "it should not update": function (res) {
        assert.equal(res.polluted, undefined);
        assert.equal(Object.prototype.polluted, undefined);
      },
    },
    "When we attempt to update the prototype using a non-string": {
      topic() {
        const obj = {};
        dotty.put(obj, [["__proto__"], "polluted"], "Muhahahaha");
        return obj;
      },
      "it should not update": function (res) {
        assert.equal(res.polluted, undefined);
        assert.equal(Object.prototype.polluted, undefined);
        const obj = {};