A severe security flaw, tracked as CVE-2024-21541, affects all versions of the popular JavaScript package dom-iterator. This vulnerability allows an attacker to execute arbitrary code on any system using the package due to unsafe use of JavaScript's Function constructor. Because the input to Function is not properly sanitized, attackers can inject malicious code, leading to a wide range of attacks—from server compromise to data exfiltration.

In this article, we’ll break down how this flaw works, provide clear code examples, walk through a proof-of-concept exploit, and share what you can do to protect your projects.

What is dom-iterator?

dom-iterator is a tool for traversing and iterating over DOM nodes in JavaScript applications. It's often used in projects that require custom DOM parsing, rendering engines, or complex browser automation. The package is publicly available on the NPM registry.

NPM page:

https://www.npmjs.com/package/dom-iterator

GitHub repo:

https://github.com/1j01/dom-iterator

The Vulnerability in Simple Terms

The root problem is that the codebase uses JavaScript’s built-in Function constructor in places where user-controlled input is passed in, without fully checking or cleaning it up (sanitization). When an attacker can influence what goes into a Function constructor, they can inject any JavaScript code they want. This is just as bad as passing user-controlled data directly to eval().

Example

let x = "alert('Hacked!')"; 
let f = new Function("return " + x); // dangerous if x comes from user input
f(); // runs alert('Hacked!')

In dom-iterator, a similar pattern exists, and no comprehensive input sanitation is provided.

Digging Into the Dangerous Code

Let’s look at a simplified version of code you might find in dom-iterator (not the actual source, but representative):

function makeFilter(predicateString) {
  // WARNING: Unsafe! Attacker can inject code if predicateString is not sanitized
  return new Function('node', 'return ' + predicateString);
}

// In application code:
let userFilter = "node.tagName === 'SCRIPT' || (() => {require('fs').writeFileSync('pwned.txt', 'owned')})()";
let filterFunc = makeFilter(userFilter);

document.querySelectorAll('*').forEach(node => {
  try {
    filterFunc(node);
  } catch(e) {}
});

Here, the use of new Function() opens the door to arbitrary code execution if predicateString comes from an attacker or untrusted source (such as user input or external data). This is exactly what is happening inside exercises commonly found in the vulnerable package.

Proof-of-Concept Exploit

Suppose an attacker can control a filter or expression string passed to dom-iterator. They can easily craft an injection to execute server-side code, steal files, escalate their privileges, or act as the user running the Node.js process.

Attack Example

const domIterator = require('dom-iterator');

// Attacker-controlled input:
const evil = "(() => {require('fs').writeFileSync('h4cked.txt', 'pwnd!')})() || true";

const filterFunc = new Function('node', 'return ' + evil);

filterFunc(); // This writes "pwnd!" to h4cked.txt on the server

If this code runs on a server (say, as part of an API or a web application for rendering or searching the DOM), the attacker now has code execution rights on that server!

Attackers can run any system command available to Node.js (child_process, fs).

- They can read/write/delete files.

How to Fix

Avoid using the Function constructor with any input that might be attacker-controlled!
Sanitization is extremely tricky and never bulletproof—so the only true solution is to refactor to never use Function with user content.

If you maintain a project using dom-iterator

- Stop using user input as a filter/predicate string.

Update to a version (if released) with a fixed implementation.

- Or switch to a safer library if a fix is not available (as of this writing, this bug is still present in all versions).

Additional References

- NPM Advisory Report, CVE-2024-21541
- Snyk Vulnerability Entry
- Node.js Docs: Function Constructor Considered Harmful

Conclusion

CVE-2024-21541 is a critical, easy-to-exploit vulnerability affecting all known versions of dom-iterator. If your project uses this library and allows users to control input to its filters or expressions, your system is wide open to attack.

Immediate action is required—disconnect any affected services until you can upgrade or remove the vulnerable code.

If you want to test for this flaw, search your codebase for any usage of Function, eval, or obvious trust of user-provided strings.

If you have more questions, reach out to your security team or trusted open source security advisors. Don’t wait—critical vulnerabilities like this one are often exploited soon after disclosure.


*Stay safe, update promptly, and never trust user input with powerful JavaScript features like Function!*

Timeline

Published on: 11/13/2024 05:15:14 UTC
Last modified on: 11/19/2024 16:20:37 UTC