Both npm and Yarn provide a mechanism to force the lockfile (
yarn.lock respectively). The lockfile prevent getting automatic updates when deploying (when doing
npm/yarn installin your server). This mechanism helps prevent malicious updates from being installed without you realizing it, but it is necessary that you always keep packages updated for possible bug fixes and improvements.
In session Dependency-based attacks it has been shown that most malicious package routines in NPM are started during installation. A few years ago an accident involving the popular eslint-scope package collected several npm tokens through Life Cycle Scripts.
Package.json supports the definition of several arbitrary scripts and their preset life cycle events. Life Cycle Scripts are scripts that execute only under certain circumstances, these scripts happen in addtion to the "pre" and "post" script, like preinstall, preuninstall, and postuninstall hooks.
A good practice would be to inspect the package.json of each dependency, however it is not feasible due to the number of packages and because they are always updating. For this reason, a good security practice is to ignore these scripts.
When installing a package, you can chose to opt out of running scripts using the
ignore-scripts option in npm or Yarn:
npm install --ignore-scripts
yarn add --ignore-scripts
It is also possible to set globally to always ignore these scripts.
npm config set ignore-scripts true
yarn config set ignore-scripts true
Whenever you use an ecosystem that uses third-party code you should know its dependencies and ask yourself questions like: "What packages do I use?", "Do I still use these packages?", "Do the packages I use have many users?", "Do my dependencies have any vulnerabilities?", "Are my dependencies up to date?".
Package managers like npm and yarn have tools to help keep your package healthy. Running
npm outdated or
yarn outdated is possible to see if their packages are outdated. Another good feature of this package manager is
npm audict and
yarn audict, functions that check for known security issues with installed packages.Another good resource to use is tools to notify you when any dependency of yours has a vulnerability like GitHub security alerts.
As previously shown, the most common way to inject malicious packages is through typosquatting, packages created by malicious users who register the package with the very similar name of some well-known package. So one way to prevent it is to know the module naming conventions well to always try to identify this type of attack.