What is prototype pollution: how object inheritance fails
Prototype pollution allows attackers to inject properties into base objects, corrupting logic and enabling remote code execution without direct memory access.

Prototype pollution occurs when an attacker manipulates the shared prototype of JavaScript objects. This injection adds unwanted properties to all instances of that object. The vulnerability arises from unsafe merging of user data into existing structures. It bypasses standard input validation by targeting the language’s inheritance mechanism rather than specific data fields.
What is prototype pollution
Prototype pollution is a vulnerability specific to JavaScript and similar languages that use prototype-based inheritance. It occurs when an attacker injects properties into the prototype of a native object, such as Object or Array. These injected properties then become accessible to all objects that inherit from that prototype. The core issue is not the data itself, but the mechanism by which the data is merged into the object structure.
Imagine a kitchen where every chef shares a single recipe book. If a saboteur writes "add arsenic" on the first page, every chef who consults that book will add arsenic to their dishes. They did not see the instruction in their specific recipe, but it is present in the shared source. Prototype pollution works by writing malicious instructions into the shared source code structure, affecting every subsequent operation that relies on it.
| Aspect | Detail |
|---|---|
| Root Cause | Unsafe merging of untrusted data into existing objects |
| Target | The prototype chain of language built-in objects |
| Impact | Logic alteration, denial of service, or remote code execution |
| Language | Primarily JavaScript, but also languages with similar inheritance |
| Detection | Difficult via static analysis; requires dynamic testing or SCA |
| Fix | Use immutable prototypes or safe merge libraries |
How the mechanism works
JavaScript objects inherit properties from a prototype. When you access a property on an object, the engine checks the object itself. If the property does not exist, it looks up the prototype chain. Prototype pollution exploits this lookup mechanism. An attacker supplies input that creates a property on the prototype itself, rather than on the specific instance.
Consider a function that merges two objects. A simple implementation might loop through the keys of the source object and assign them to the target. If the source contains a key like __proto__ or constructor.prototype, the assignment operator modifies the base prototype. All future objects created from that prototype will now have the new property. This happens silently, without error messages, because the language treats the assignment as valid.
The danger lies in the breadth of the effect. A single polluted prototype affects every part of the application that uses that object type. If an attacker injects a property called isAdmin and sets it to true, every user object in the system might suddenly appear to be an administrator. The application logic trusts the property because it exists on the object, unaware that it was inherited from a compromised source.
Who it affects
Prototype pollution affects any application written in languages that rely on prototype-based inheritance. JavaScript is the most common target because it is the dominant language for web browsers and server-side environments like Node.js. However, any environment using similar mechanisms is at risk. The vulnerability is not limited to web applications; it can exist in desktop applications, mobile apps, and serverless functions that use these languages.
Developers who build libraries that merge or clone objects are particularly exposed. If a widely used library contains a vulnerable merge function, every application that depends on it inherits the risk. This creates a supply chain issue. You might write secure code, but if your dependencies are vulnerable, your application is compromised. This is why software composition analysis is relevant for identifying vulnerable dependencies in your project tree.
Security teams often overlook this class of vulnerability because it does not involve traditional memory corruption. There is no buffer overflow. There is no direct injection of shell commands. The attack is logical, not structural. This makes it harder to detect with standard tools that look for known exploit patterns. It requires an understanding of how the language handles object inheritance and property resolution.
What people usually get wrong
Many developers believe that input validation prevents prototype pollution. They validate that user input contains only allowed characters or matches a specific format. This approach fails because the attack vector is not the content of the data, but the key names used to store it. A valid string like __proto__ is not inherently malicious. It becomes dangerous only when used as a key in an object merge operation.
Another common misconception is that sanitising input by removing known dangerous keys is sufficient. Attackers can use alternative paths to reach the prototype. For instance, they might use constructor.prototype or other indirect references. A blacklist approach is inherently fragile. It requires knowing every possible path to the prototype. New paths can emerge with language updates or library changes.
Some teams assume that using modern frameworks eliminates the risk. While some frameworks include safe merge functions, others do not. Custom code often bypasses framework protections. Developers might write their own merge logic to achieve specific performance or formatting goals. This custom code frequently reintroduces the vulnerability. The risk is not in the framework, but in the specific implementation of data merging.
Mitigations and workarounds
The most effective defence is to avoid merging untrusted data into existing objects. If merging is necessary, use libraries that are explicitly designed to be safe against prototype pollution. These libraries check for dangerous keys like __proto__ and constructor and refuse to assign them. They may also use immutable prototypes, which prevent modification of the base object structure.
Another approach is to freeze the prototype. JavaScript provides methods to make objects immutable. If the prototype is frozen, any attempt to add or modify properties on it will fail. This prevents the pollution from taking hold. However, this can break legitimate functionality if your application relies on dynamic property addition. You must balance security with feature requirements.
You can also implement strict schema validation. Instead of merging objects, define a strict schema for the expected data structure. Map the user input to this schema explicitly. This ensures that only known properties are created. Any unknown keys, including __proto__, are discarded. This approach requires more upfront design work but provides a strong barrier against unexpected property injection.
Dependency updates and patch management
Since prototype pollution often resides in third-party libraries, keeping dependencies up to date is a critical control. Many popular libraries have released patches that fix vulnerable merge functions. Regular dependency updates ensure you benefit from these fixes. This ties into your broader patch management strategy. You must treat library updates with the same urgency as operating system patches.
Automating this process helps. Use tools that monitor your dependencies for known vulnerabilities. When a fix is released, the tool should alert you and potentially create a pull request to update the version. This reduces the window of exposure. It also ensures that your team does not overlook updates amidst other development tasks.
However, updating dependencies is not a silver bullet. New libraries may introduce new vulnerabilities. You must verify that the updated version does not break your application. Regression testing is essential. You should also review the changelog of the library to understand what was fixed. This helps you understand the nature of the vulnerability and whether your application was actually exposed.
Coordinated vulnerability disclosure
If you discover a prototype pollution vulnerability in a library you use, responsible disclosure is important. The library maintainers may not be aware of the issue. Reporting it allows them to fix the root cause. This helps the entire ecosystem, not just your application. Many libraries have a coordinated vulnerability disclosure process. Follow their guidelines to report the issue privately.
Do not publish details of the vulnerability until a fix is available. Public disclosure without a fix allows attackers to exploit the vulnerability before users can patch it. This causes widespread harm. Wait for the maintainers to release a patch and verify that it works. Then, you can share your findings if appropriate. This ethical approach builds trust within the security community.
Understanding how to report vulnerabilities is a valuable skill. It demonstrates professionalism and a commitment to security. It also helps you stay informed about emerging threats. By engaging with library maintainers, you gain insight into how they handle security issues. This knowledge can inform your own development practices and help you avoid similar mistakes.

Software composition analysis
Software composition analysis tools can help identify libraries that are known to be vulnerable to prototype pollution. These tools scan your dependency tree and compare it against databases of known vulnerabilities. They provide a bill of materials for your project. This visibility is crucial for managing risk in complex applications.
Integrate software composition analysis into your continuous integration pipeline. This ensures that every build is checked for vulnerable dependencies. If a new vulnerability is disclosed, the pipeline will fail if your project uses the affected library. This prevents vulnerable code from reaching production. It shifts security left in the development lifecycle.
However, these tools are not perfect. They may miss vulnerabilities in custom code or in libraries that are not yet known to be vulnerable. They also cannot detect logic errors that lead to pollution in unique ways. Use them as part of a broader security strategy. Combine automated scanning with manual code review and secure coding practices.
Key takeaways
- User input merged with existing objects can overwrite inherited properties if merge logic lacks deep protection.
- The attack vector targets the prototype chain, affecting all objects that inherit from the compromised base.
- Standard input sanitisation often fails because it validates data content, not the structural impact on object inheritance.
- Mitigation requires using immutable prototypes or libraries that explicitly block property assignment to inherited keys.
Prototype pollution exploits the inheritance mechanism of the language, not just data validation. Always use safe merge libraries or immutable prototypes when handling untrusted data.
Frequently asked questions
Does prototype pollution affect Python or Java?
No, these languages use class-based inheritance. They do not have a prototype chain that can be polluted in the same way. They have different vulnerability classes, such as deserialization flaws.
Can I fix prototype pollution by just filtering `__proto__`?
No, attackers can use alternative paths like `constructor.prototype`. You need a comprehensive solution that blocks all paths to the prototype or uses immutable structures.
Is prototype pollution a remote code execution vulnerability?
It can be. If the polluted property influences code execution, such as a file path or a function name, an attacker can achieve remote code execution. It often starts with logic alteration.
How do I test for prototype pollution?
Use dynamic analysis tools that monitor object property changes. You can also write specific test cases that attempt to inject `__proto__` and check if the base prototype is modified.
How this guide was produced: written by the Malware Brief editorial team with AI assistance, checked against the public references listed below, and reviewed when the facts change. See our editorial policy or report an error.



