{"id":"GHSA-82jv-9wjw-pqh6","aliases":[],"status":"published","title":"Prototype pollution in emit function","description":"### Summary\nA prototype pollution in derby can crash the application, if the application author has atypical HTML templates that feed user input into an object key.\n\nAttribute keys are almost always developer-controlled, not end-user-controlled, so this shouldn't be an issue in practice for most applications.\n\n### Details\n```\nemit(context: Context, target: T) {\n  const node = traverseAndCreate(context.controller, this.segments);\n    node[this.lastSegment] = target;\n    this.addListeners(target, node, this.lastSegment);\n}\n```\nThe emit() function in src/templates/templates.ts is called without sanitizing the variable `this.lastSegment `. The variable `this.lastSegment ` can be set to `__proto__`, and this will pollute the prototype of Javascipt Object (`node['__proto__'] = target`).\n\n### PoC\nTo reproduce this vulnerability, you can adjust the test case `ignores DOM mutations in components\\' create()` in `test/dom/ComponentHarness.mocha.js`.\n\n```\nit('ignores DOM mutations in components\\' create()', function() {\n      function Box() {}\n      Box.view = {\n        is: 'box',\n-        source: '\u003cindex:\u003e\u003cdiv class=\"box\" as=\"boxElement\"\u003e\u003c/div\u003e'\n+        source: '\u003cindex:\u003e\u003cdiv class=\"box\" as=\"__proto__\"\u003e\u003c/div\u003e'\n      };\n      Box.prototype.create = function() {\n        this.boxElement.className = 'box-changed-in-create';\n      };\n      var harness = runner.createHarness('\u003cview is=\"box\" /\u003e', Box);\n      expect(harness).to.render('\u003cdiv class=\"box\"\u003e\u003c/div\u003e');\n});\n```\nWhen `as` attribute is controlled by attackers, the variable in `this.lastSegment` will exactly take value` __proto__` and prototype pollution happens.\n\n### Patch\nAdd a check on `this.lastSegment` can prevent this attack.\n```\nemit(context: Context, target: T) {\n  const node = traverseAndCreate(context.controller, this.segments);\n+  if (this.lastSegment.includes('__proto__') || this.lastSegment.includes('prototype')) {\n+    throw new Error('Unsafe code detected');\n+  }\n    node[this.lastSegment] = target;\n    this.addListeners(target, node, this.lastSegment);\n}\n```","facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-1321"],"published":"2024-04-17T22:26:37Z","modified":"2024-04-17T22:26:38Z","fixes":[{"ecosystem":"npm","package":"derby","fixed_in":["2.3.2","3.0.2","4.0.0-beta.11"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"derby","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"2.3.1"},{"fixed":"2.3.2"}]}]},{"source":"ghsa","ecosystem":"npm","package":"derby","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.0.0"},{"last_affected":"3.0.1"},{"fixed":"3.0.2"}]}]},{"source":"ghsa","ecosystem":"npm","package":"derby","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.0.0-beta1"},{"last_affected":"4.0.0-beta.10"},{"fixed":"4.0.0-beta.11"}]}]},{"source":"osv","ecosystem":"npm","package":"derby","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"2.3.2"}]}]},{"source":"osv","ecosystem":"npm","package":"derby","ranges":[{"type":"SEMVER","events":[{"introduced":"3.0.0"},{"fixed":"3.0.2"}]}]},{"source":"osv","ecosystem":"npm","package":"derby","ranges":[{"type":"SEMVER","events":[{"introduced":"4.0.0-beta1"},{"fixed":"4.0.0-beta.11"}]}]}],"references":[{"url":"https://github.com/derbyjs/derby/security/advisories/GHSA-82jv-9wjw-pqh6","tags":["web"]},{"url":"https://github.com/derbyjs/derby/commit/24524e96f36976883c7c619811320428536bd4d0","tags":["web"]},{"url":"https://github.com/derbyjs/derby/commit/465a0c2f6a77361eda4a09b77a8c94ba6a9da440","tags":["web"]},{"url":"https://github.com/advisories/GHSA-82jv-9wjw-pqh6"},{"url":"https://github.com/derbyjs/derby","tags":["package"]}],"sources":{"ghsa":[{"id":"GHSA-82jv-9wjw-pqh6","title":"Prototype pollution in emit function","description":"### Summary\nA prototype pollution in derby can crash the application, if the application author has atypical HTML templates that feed user input into an object key.\n\nAttribute keys are almost always developer-controlled, not end-user-controlled, so this shouldn't be an issue in practice for most applications.\n\n### Details\n```\nemit(context: Context, target: T) {\n  const node = traverseAndCreate(context.controller, this.segments);\n    node[this.lastSegment] = target;\n    this.addListeners(target, node, this.lastSegment);\n}\n```\nThe emit() function in src/templates/templates.ts is called without sanitizing the variable `this.lastSegment `. The variable `this.lastSegment ` can be set to `__proto__`, and this will pollute the prototype of Javascipt Object (`node['__proto__'] = target`).\n\n### PoC\nTo reproduce this vulnerability, you can adjust the test case `ignores DOM mutations in components\\' create()` in `test/dom/ComponentHarness.mocha.js`.\n\n```\nit('ignores DOM mutations in components\\' create()', function() {\n      function Box() {}\n      Box.view = {\n        is: 'box',\n-        source: '\u003cindex:\u003e\u003cdiv class=\"box\" as=\"boxElement\"\u003e\u003c/div\u003e'\n+        source: '\u003cindex:\u003e\u003cdiv class=\"box\" as=\"__proto__\"\u003e\u003c/div\u003e'\n      };\n      Box.prototype.create = function() {\n        this.boxElement.className = 'box-changed-in-create';\n      };\n      var harness = runner.createHarness('\u003cview is=\"box\" /\u003e', Box);\n      expect(harness).to.render('\u003cdiv class=\"box\"\u003e\u003c/div\u003e');\n});\n```\nWhen `as` attribute is controlled by attackers, the variable in `this.lastSegment` will exactly take value` __proto__` and prototype pollution happens.\n\n### Patch\nAdd a check on `this.lastSegment` can prevent this attack.\n```\nemit(context: Context, target: T) {\n  const node = traverseAndCreate(context.controller, this.segments);\n+  if (this.lastSegment.includes('__proto__') || this.lastSegment.includes('prototype')) {\n+    throw new Error('Unsafe code detected');\n+  }\n    node[this.lastSegment] = target;\n    this.addListeners(target, node, this.lastSegment);\n}\n```\n","status":"published","published":"2024-04-17T22:26:37Z","modified":"2024-04-17T22:26:38Z","cwes":["CWE-1321"],"updated_at":"2026-11-02T14:37:43.62603Z"}],"osv":[{"id":"GHSA-82jv-9wjw-pqh6","title":"Prototype pollution in emit function","description":"### Summary\nA prototype pollution in derby can crash the application, if the application author has atypical HTML templates that feed user input into an object key.\n\nAttribute keys are almost always developer-controlled, not end-user-controlled, so this shouldn't be an issue in practice for most applications.\n\n### Details\n```\nemit(context: Context, target: T) {\n  const node = traverseAndCreate(context.controller, this.segments);\n    node[this.lastSegment] = target;\n    this.addListeners(target, node, this.lastSegment);\n}\n```\nThe emit() function in src/templates/templates.ts is called without sanitizing the variable `this.lastSegment `. The variable `this.lastSegment ` can be set to `__proto__`, and this will pollute the prototype of Javascipt Object (`node['__proto__'] = target`).\n\n### PoC\nTo reproduce this vulnerability, you can adjust the test case `ignores DOM mutations in components\\' create()` in `test/dom/ComponentHarness.mocha.js`.\n\n```\nit('ignores DOM mutations in components\\' create()', function() {\n      function Box() {}\n      Box.view = {\n        is: 'box',\n-        source: '\u003cindex:\u003e\u003cdiv class=\"box\" as=\"boxElement\"\u003e\u003c/div\u003e'\n+        source: '\u003cindex:\u003e\u003cdiv class=\"box\" as=\"__proto__\"\u003e\u003c/div\u003e'\n      };\n      Box.prototype.create = function() {\n        this.boxElement.className = 'box-changed-in-create';\n      };\n      var harness = runner.createHarness('\u003cview is=\"box\" /\u003e', Box);\n      expect(harness).to.render('\u003cdiv class=\"box\"\u003e\u003c/div\u003e');\n});\n```\nWhen `as` attribute is controlled by attackers, the variable in `this.lastSegment` will exactly take value` __proto__` and prototype pollution happens.\n\n### Patch\nAdd a check on `this.lastSegment` can prevent this attack.\n```\nemit(context: Context, target: T) {\n  const node = traverseAndCreate(context.controller, this.segments);\n+  if (this.lastSegment.includes('__proto__') || this.lastSegment.includes('prototype')) {\n+    throw new Error('Unsafe code detected');\n+  }\n    node[this.lastSegment] = target;\n    this.addListeners(target, node, this.lastSegment);\n}\n```\n","status":"published","published":"2024-04-17T22:26:37Z","modified":"2024-04-17T22:26:37Z","cwes":["CWE-1321"],"updated_at":"2026-11-02T15:46:41.732368Z"}]}}
