CVE-2021-23624 (JavaScript, published 2021-11-03T18:15Z)
Description: 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.
Severity: HIGH (CVSS v3 base score: 9.8)
Weakness: CWE-843 \u2014 Access of Resource Using Incompatible Type ('Type Confusion')
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.
Repository: https://github.com/deoxxa/dotty
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 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

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 = {};