Socket is proud to introduce an exciting new tool—“safe npm”—that protects developers whenever they use npm install
.
Socket’s “safe npm” CLI tool transparently wraps the npm
command and protects developers from malware, typosquats, install scripts, protestware, telemetry, and more—11 issues in all.
The most dangerous command you run every day: npm install
#
Today, when you run npm install
it's difficult to know which transitive packages will get installed, whether those packages will execute "install scripts", or if those packages have been compromised by malware.
The average npm package has 79 transitive dependencies. That means installing a single package with npm install
will, on average, install 80 total packages. It’s hard—if not impossible—for a developer to audit, let alone even understand, the full list of packages that will be installed. Most of us just cross our fingers and hope for the best.
Worryingly, any of these 80 packages can declare an install script—third-party shell code—that npm
will automatically execute during installation. While there are legitimate use cases for install scripts, it's also a favorite feature of malware authors: 94% of malicious packages used at least one install script.
Developers also face the ever-present risk of typo-squatting attacks, where an attacker publishes a package with a name similar to a more popular package. It's way too easy for a busy developer to make a typo when running npm install
and install the wrong package. Sometimes, however, typos can have disastrous consequences such as in the case of running npm install webb3
instead of npm install web3
. Just take a look at what was hiding in the typo'd version:
This type of malware is all too common. Socket has seen over 200 packages removed for security reasons (malware, ransomware, spam, etc.) in the past 30 days alone. To help you get a sense of the scale of the problem, we freely share samples of recently removed npm packages with the public, for non-commercial research use.
In Search of a Solution#
In conversations with developers, we kept hearing the same request. Developers want a way to securely and confidently run npm install
without the fear of malware or rogue scripts infecting their system.
Our most popular product, Socket for GitHub, already proactively scans GitHub pull requests for software supply chain risks—including typo-squats, install scripts, and 70+ customizable issues—but until today, we haven’t had a good way to protect the developer’s local machine from bad packages.
That's why we're super excited to share this initial release of “safe npm” with you today!
Introducing "safe npm", a Security Wrapper for npm#
Socket is proud to introduce a new feature—“safe npm”—that protects developers whenever they use npm install
. The feature transparently wraps the npm
and npx
commands to protect developers from malware, typosquats, install scripts, protestware, telemetry, and more, during the installation process.
When a developer attempts to install a malicious or risky package, Socket pauses the installation and informs the developer about the risk. The developer is given the option to stop the installation and protect their machine before the package is executed or even written to disk. Alternatively, the developer is also free to proceed and accept the risks.
Here's what it looks like in action:
If no security risks are present, the installation will proceed as normal without any interruption to the developer workflow. Socket works with all of the npm commands that can install new third-party code, including:
npm install
– including the numerous variants npm i
, npm in
, npm ins
, npm inst
, etc.npm update
npm uninstall
and npm rm
– which can actually install packages! (See the FAQ below for an explanation)npm exec
and npx
.
In case you didn't know, there are a lot of ways to install packages with npm!
Socket runs the real npm
installation process and analyzes the results—including deeply nested dependencies—before anything is written to disk. It also performs wrapping to ensure spawning child processes and npm run
properly preserve our npm wrapper.
Protect your Terminal with Socket
To get started, install the Socket CLI by running npm install -g @socketsecurity/cli
. This adds a socket
command to your PATH.
Then, use socket npm
wherever you used npm
before. For example, instead of npm install react
instead run socket npm install react
to transparently analyze your dependencies with Socket.
We encourage developers to consider adding alias npm="socket npm"
and alias npx="socket npx"
to their .bashrc
profiles so they can keep typing npm install
—preserving muscle memory—while transparently benefiting from this security protection.
A word about npx
This type of protection is even more needed for commands like npx
and npm exec
where code is immediately run, rather than being installed as a dependency. Due to the prolific usage of these commands, we made sure to add protection for these commands too, so that you don't accidentally run bad code by copy-pasting an npx
command from a README file or StackOverflow answer and get compromised.
Here's how Socket works with npx
:
As always, we are trying to expand our capabilities to serve our users. Please try out this feature by running npm install -g @socketsecurity/cli
and please let us know what you think!
We are @SocketSecurity on Twitter and @SocketSecurity@fosstodon.org on Mastodon. We'd love to hear what you think, and please give us a shout if this feature serves you well!
FAQ#
What is Socket?
Socket fights vulnerabilities and provides visibility, defense-in-depth, and proactive supply chain protection for JavaScript and Python dependencies.
The Socket team are all prolific open source maintainers (our open source packages collectively have 1 billion+ downloads per month). Socket customers include Vercel, Replit, and Brave. Socket is also used by prominent open source projects such as Next.js, Storybook, and Metamask.
You can install Socket for GitHub for free, in less than 2 minutes.
How do I start using "safe npm"?
Install the Socket CLI by running npm install -g @socketsecurity/cli
– that's it!
That command will add a socket
binary to your PATH. Then, you can use socket npm install
instead of npm install
to benefit from Socket’s protections.
Just check that you're using version 0.5.1 or later to get the “safe npm” feature. You can verify the version you're using with socket --version
.
How can I use this without replacing all my code that uses npm
?
socket npm
will automatically detect if it is in front of npm
in the PATH
variable, and if it is not it will prepend itself to the PATH
to intercept commands. This means if you use something like socket npm run script-with-npx
it will already intercept npx
without you needing to change your package.json
.
For people wishing to avoid typing out socket npm
a shell alias like the following in your .bashrc
or .zsh
:
alias npm="socket-npm"
alias npx="socket-npx"
For zsh
autocompletions you may wish to add the following as well:
compdef _npm socket-npm
For bash
autocompletions you may wish to add the following as well:
$(complete -p npm | sed 's/npm$/socket-npm/')
How does Socket detect bad packages?
Socket uses static analysis, which is a technique that involves analyzing source code without actually executing it, to identify potential indicators of software supply chain attacks. This includes looking for new install scripts, network requests, environment variable access, telemetry, suspicious strings, obfuscated code, and dozens of other signals, all of which can be signs of malicious activity. We use a custom static analysis engine developed in-house to analyze every package across the entire npm and PyPI ecosystems (and very soon, Go, Maven, etc.).
In addition to static analysis, Socket also analyzes maintainer behavior. This means we look at who is maintaining the package and their activity history. This is important because a package with a history of questionable maintenance or a new maintainer with no track record can be a red flag for potential attacks. We also warn about unmaintained packages, trivial packages, and packages which have recently undergone major refactors.
Socket also analyzes package metadata to identify signs that a package is risky. For example, a package may load code from a remote git repository or a remote HTTP server, totally bypassing your package lockfile. This allows attackers to load whatever code they want, and even serve different packages to different IP addresses, making it really hard to have a reproducible build or figure out what code is actually going to be run when you install a package.
Another use of package metadata is to detect typosquats. We use name similarity and download counts to detect packages which impersonate other legitimate packages. For example webb3 is a malicious typo of web3 because the name is similar and the legitimate package has 300,000 times as many downloads as the malicious one.
In total, we look for 70+ signals in open source packages, which use different combinations of these 3 techniques – static analysis, package metadata analysis, and maintainer behavior analysis. By identifying attack indicators early, before the PR is merged, Socket helps prevent attacks before they can do any damage.
What are the limitations in this initial release?
For our initial release of the "safe npm" wrapper we only support default socket.yml settings. That means that Socket will catch the following issues:
- Bin script shell injection
- Git dependency
- HTTP dependency
- Install scripts
- Known Malware
- Native code
- Potential typo squat
- Protestware/Troll package
- Telemetry
- Quality
- Invalid package.json
- Unresolved require
We hope to gather feedback and expand the capabilities to support the full range of Socket configuration options and rules in a future release.
Why do I see an alert when using socket npm uninstall foo
?
You might think that removing a package could never cause a new package to be installed, but you'd be mistaken! It's possible for npm uninstall
or npm rm
to actually install new packages.
So, as counterintuitive as it might seem, you also need to be careful when running npm uninstall
. Fortunately, Socket protects you in that situation if you use socket npm uninstall
– so not to worry!
Wait, why would npm uninstall
ever install new packages?
npm
creates what is called the "ideal tree" for a given package.json
. So by removing a package you might actually change what the ideal tree is. Removing a package may remove a constraint which is keeping a package on an older version, so then npm may update those packages to a more ideal/recent version.
For example, if foo
depends on bar@1.1.x
it will constrain bar
to be on 1.1.x
but a different dependency baz
might depend on on bar@1.x.x
which constrains bar
to any version 1.x.x
. If bar@1.2.0
exists it would be available to use if foo
is removed from the package.json
!
This "ideal tree” step also performs automatic updates when using npm install
in its default configuration. If a package bar
exists in your package.json
it will automatically be updated upon being found even if what you’re installing is unrelated to bar
in any way.
Why am I seeing alerts for an unrelated package when using socket npm install foo
?
Same reason as above.
When will you support yarn
and pnpm
?
Socket supports yarn and pnpm throughout the product. See our full list of supported language ecosystems and package managers for more information.
However, for this initial release of "safe npm", we only support npm
When will you support pip
, poetry
, etc.?
Socket supports Python. Specifically, Socket for GitHub already supports pip, poetry, and other popular Python package managers. You can read the announcement where we introduced Python support.
If you would like to see support for "safe pip" functionality, similar to "safe npm", please vote for this feature request here. With enough demand, we'd love to bring this feature to more ecosystems!
How is the wrapper implemented?
There were lots of interesting things we had to do in order to completely cover various situations in npm
and avoid some escapes that would bypass our wrapper. When you alias the wrapper with alias npm="socket npm"
it would have been buggy if we didn't guard against basic child process invocation. For example running npm run
will invoke a child process that can remove that alias. To that end, we are doing some tricks to protect against this. More information can be found in our documentation.
If you'd like to get involved and contribute to the CLI, the codebase is online here: https://github.com/SocketDev/socket-cli-js