Open Nav
Sign Up

Prototype Pollution high vulnerability in ‘mixme’ NPM package

Dan Shallom

May 5, 2021

TL;DR

  • Learn about JavaScript Prototypes
  • Learn about Prototype Pollution
  • Introducing the Prototype Pollution vulnerability that OP Innovate discovered on mixme.
  • Mitigation & helpful tools and utilities.
  • https://nvd.nist.gov/vuln/detail/CVE-2021-28860 ; https://nvd.nist.gov/vuln/detail/CVE-2021-29491
  • https://www.npmjs.com/advisories/1668

NPM (Node Package Manager) is a gigantic software registry that contains hundreds of thousands of open source Node.js projects in the form of packages. As a matter of fact, if a developer wanted to share their code with the world, NPM would be a good way to do it.

If you read one of my previous articles entitled “DLL Injection Attack in Kerberos NPM package” you may recall a section describing the dangerous universe of open-source code. In short, open-source packages are often implemented without security in mind, potentially impacting the overall security of the consumers – large corporations or single users, it doesn’t really matter.

JavaScript Inheritance

Before we dive in, let’s remind ourselves of some JavaScript essentials. JavaScript is a very popular and well-known scripting language used in web pages, and notably for our current context, is a prototype-based programming language.

👉 What is a prototype? a prototype is an object and a property of an object. An object can have another object as its prototype. The base object can inherit all of its prototype’s attributes. The chain of objects connected by the prototype property is called Prototype Chain.

Figure 1 – prototypes

👉What is “__proto__”? At the time an object is created it gets the property of “__proto__”. ”__proto__” is an accessor property that points to the prototype object of the constructor function. “__proto__” is a way to inherit properties from an object in JavaScript.

Figure 2 – __proto__

For example, in this case the ModelX’s and ModelY’s proto will point to the same prototype object of the constructor function (Vehicle).

ModelX.__proto__ === ModelY.__proto__

The prototype object of the constructor function (in this case “Vehicle”) is shared by all the objects that were created by the constructor function (in this case “Vehicle”).

Put your protective masks on – it’s Prototype Pollution Time!

As we saw in the previous example, when an object accesses its “__proto__” it will point to the prototype object of the constructor function, meaning it will have access to the properties of the base class Vehicle (While Vehicle will inherit them from Vehicle’s prototype).

But what happens if we change an existing attribute or add a new one through the “__proto__” of an object? 

ModelX.__proto__.polluted = "Just got polluted !!"

The answer to this question is quite simple – every object within the running application will get the “polluted” attribute, and will be able to access the “polluted” attribute, directly – without needing to call the “proto”. In most cases the application will not be able to handle this situation. This will damage the application’s availability, leading it to crash. In other cases it will be possible to execute code. In short, the “polluted” attribute will affect the entire prototype chain!

But how can this dangerous situation happen in the wild?
A lot of packages out there use MERGE/SET-like operations. These kinds of functions usually take two parameters and assign one to the other. The big issue here is that in most cases these operations allow an attacker to intervene and affect the entire prototype chain by tampering or adding a new property to an object via “proto”.

Prototype Pollution in ‘mixme’ NPM package

‘Mixme’ package allows merging multiple objects recursively. It has 6 functions:
◼ merge(…data)
◼ mutate(…data)

◼ clone(data)
◼ is_object_literal(object)
◼ snake_case(object)
◼ compare(item_1, item_2)


We will examine the merge and mutate methods. The merge method is based mainly on the mutate function that is recursively implemented. It takes multiple parameters as an input, merges them and returns the merged value. Usually recursion is the best method to implement such utilities.
For example, this function call:

mutate({a: '1'}, {b: '2'})

Will output the following:

{a: '1', b: '2'}

Now let’s try something else – instead of merging vague parameters, we will try using the mutate function (MERGE operation) in a non-legitimate way. We’ll use two arguments for the mutate() function:

◼ Base object – {}
◼ Nested object – JSON.parse(‘{“proto“: {“polluted”: “Just polluted!!!”}}’)

JSON.parse will construct a JavaScript nested object:

{
     "__proto__":{
     "polluted":"Just polluted!!!"
     }
}

The POC:

const {merge} = require("C:\node_modules\mixme");
var base_obj = {}
console.log("Before MERGE: " + base_obj.polluted);
merge({}, JSON.parse('{"__proto__": {"polluted": "Just polluted!!!"}}'))
console.log("After MERGE: " + base_obj.polluted);
var obj_NEW =[]
console.log("obj_NEW also get the polluted attribute with the value of:" + obj_NEW.polluted)
  • Before the mutate() is called, the base object doesn’t contain the “polluted” attribute:
    • The value of base_obj.polluted is undefined.
  • But right after the MERGE operation, the base object and every other object in that runtime will have the “polluted” attribute:
    • The value of base_obj.polluted is “Just polluted!!!”.
    • Every object will now have the polluted attribute with the “Just polluted!!!” value. Following the MERGE operation, we created obj_NEW and printed the obj_NEW.polluted. The value is the same as base_obj.polluted (“Just polluted!!!”).

Figure 3 – console’s output

Let’s take a look over on object fields at the last iteration

Figure 4 – mutate() last iteration

Figure 5 – {}.__proto__.polluted=“Just polluted!!!”

So, basically this command –

merge({}, JSON.parse('{"__proto__": {"polluted": "Just polluted!!!"}}'))

Leads to the following assignment –

{}.__proto__.polluted="Just polluted!!!"

Prototype Pollution – mitigation

There are a couple of main points you should relate to when applying when considering a resolution:

💡Make sure to use safe recursive merge functions (harden ‘mutate’ function in this case)
💡Don’t allow the input to begin with “proto” field
💡Update 3rd party libraries and maintain a best practice policy for keeping them updated whenever an update is released

The following graph represent the number of downloads per day for ‘mixme’ package, during the last year:

Figure 6 – Taken from “npm-stat.com”

Takeaway

Prototype pollution is an underrated vulnerability that until recently didn’t get the proper attention. There are a lot of affected products that make use of insecure MERGE operations.

Written by Dan Shallom, Cyber security researcher | Certified Ethical Hacker (CEH) | Certified Security Analyst – Practical (ECSA)

Resources highlights

CVE-2026-20127 & CVE-2022-20775: Active Exploitation of Cisco SD-WAN Systems

A coordinated global campaign targeting Cisco SD-WAN environments has been identified by CISA, NSA, and international partners. Threat actors are actively exploiting a chain of…

Read more >

CVE-2026-20127

CVE-2025-49113 & CVE-2025-68461: Actively Exploited Roundcube Webmail Vulnerabilities

Two critical vulnerabilities affecting Roundcube Webmail, a widely deployed web-based email client (commonly bundled with cPanel), have been confirmed as actively exploited in the wild.…

Read more >

CVE-2025-49113

CVE-2026-20140: Splunk Enterprise for Windows Local Privilege Escalation

Splunk disclosed a high-severity local privilege escalation (LPE) vulnerability affecting Splunk Enterprise for Windows. An attacker with low-privileged local access may be able to escalate…

Read more >

CVE-2026-20140

CVE-2026-22769: Critical Dell RecoverPoint Hardcoded Credential Vulnerability

A critical vulnerability, CVE-2026-22769 (CVSS 10.0), has been identified in Dell RecoverPoint for Virtual Machines, a widely used enterprise backup and disaster recovery solution for…

Read more >

CVE-2026-22769

Google Chrome Zero-Day Under Exploitation (CVE-2026-2441)

CVE-2026-2441 is a high-severity use-after-free vulnerability in Google Chrome that is actively exploited in the wild. This marks the first Chrome zero-day patched in 2026.…

Read more >

CVE-2026-2441

Actively Exploited BeyondTrust RCE (CVE-2026-1731)

CVE-2026-1731 is a critical remote code execution (RCE) vulnerability affecting BeyondTrust Remote Support and Privileged Remote Access solutions. The flaw is actively exploited in the…

Read more >

CVE-2026-1731
Under Cyber Attack?

Fill out the form and we will contact you immediately.