Skip to content

fix: use hasOwnProperty instead of 'in' operator in assignOrPush#720

Open
abhu85 wants to merge 1 commit intoLeonidas-from-XIV:masterfrom
abhu85:fix/719-prototype-chain-bypass
Open

fix: use hasOwnProperty instead of 'in' operator in assignOrPush#720
abhu85 wants to merge 1 commit intoLeonidas-from-XIV:masterfrom
abhu85:fix/719-prototype-chain-bypass

Conversation

@abhu85
Copy link
Copy Markdown

@abhu85 abhu85 commented Mar 13, 2026

Summary

  • Fix prototype chain traversal vulnerability in assignOrPush method
  • Add regression tests for XML tags named after Object.prototype methods
  • This is a security fix - bypass of CVE-2023-0842

Problem

The assignOrPush method uses the JavaScript in operator to check if a key exists:

if (!(key in obj)) { ... }

The in operator traverses the prototype chain, which means tags named after inherited Object.prototype methods (<toString>, <valueOf>, <constructor>, <hasOwnProperty>, etc.) are incorrectly treated as pre-existing properties.

This causes inherited functions to be mixed with user data in arrays, breaking the parsed object and causing TypeError crashes:

const xml2js = require('xml2js');
xml2js.parseString('<root><toString>x</toString></root>', (err, result) => {
    console.log(result.root.toString); // [ [Function: toString], 'x' ]
    console.log(result.root.toString.join(', ')); // TypeError!
});

Note: This is NOT a duplicate of CVE-2023-0842. That fix correctly prevents prototype pollution when writing properties via defineProperty. This vulnerability is in the reading/checking of property existence via the in operator.

Solution

Replace key not of obj (CoffeeScript in operator) with Object::hasOwnProperty.call obj, key to only check own properties, not inherited ones.

Test Plan

Compatibility

  • No breaking API changes
  • Backwards compatible - previously broken XML now parses correctly
  • No new dependencies

Fixes #719

🤖 Generated with Claude Code

…nidas-from-XIV#719)

The `in` operator in JavaScript traverses the prototype chain, which means
tags named after inherited Object.prototype methods (toString, valueOf,
constructor, hasOwnProperty, etc.) were incorrectly treated as pre-existing
properties.

This caused inherited functions to be mixed with user data in arrays,
breaking the parsed object and causing TypeError crashes on normal usage.

This is a bypass of the CVE-2023-0842 fix. That fix correctly prevents
prototype pollution when *writing* properties via defineProperty, but
this vulnerability is in the *reading/checking* of property existence.

Fix: Replace `key not of obj` with `Object::hasOwnProperty.call obj, key`
to only check own properties, not inherited ones.

Fixes Leonidas-from-XIV#719

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Security: Inherited Property Confusion in assignOrPush causes DoS (bypass of CVE-2023-0842 fix)

1 participant