Preventing prototype pollution in your repository
If you arrived on this page directly from an Aikido Autofix Pull Request and just want to learn how to finish the PR, skip to ‘How to implement’.
The JavaScript ecosystem has a problem and it’s called prototype pollution. For a SaaS company building with JavaScript/npm, typically up to 20-30% of all known vulnerabilities (CVE) detected in the dependencies are caused by prototype pollution. They are usually not easy to exploit, but in bad cases, they can lead to remote code execution flaws. That means they are hard to ignore altogether.
Two ways to prevent prototype pollution
There is experimental support in Node.js to freeze the prototype by default under a flag called --frozen-intrinsics. Enabling that flag defeats all prototype pollution attacks. However, we can’t recommend it yet because it’s experimental and it also won’t work on frontend codebases. That would prevent you from building the same protection across your frontend and backend.
An alternative is nopp (No Prototype Pollution), a 14-line library that freezes the prototype (and some other entry points).
How to implement
1. Importing the library
After you’ve installed nopp, all you have to do is go to the script that starts your app. There you simply require the library, after you’ve required all your other libraries. Example commit below:
2. App-wide safety check for libraries depending on prototype manipulation
The reason we’re freezing the prototype after including other libraries is that some of your other libraries may rely on changing the prototype to work! Even after making sure to freeze the prototype AFTER including other libraries, it’s still possible you will need some refactoring before your app works again!
Case in point, Amazon’s own aws-sdk for Node.js makes changes to the prototype during the construction of objects such as “new AWS.S3(..)”. In such cases, you might have to do a refactor as shown below, making sure the object is created when your Node.js process is booted and not during a later phase.
Making sure your app still works after this change might be a bigger time investment for larger repositories that have low test coverage. For smaller repositories, it’ll be worth it to never have to deal with prototype pollution again. For bigger repositories, this might be more complex, but the engineering investment will likely still have a positive ROI over the longer term.