Signing is Just the Start
Socket provides an introspective on code signing in relation to the supply chain incident from SolarWinds.
March 16, 2023
Socket is proud to introduce an exciting new tool—“safe npm”—that protects developers whenever they use
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.
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 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!
Socket is proud to introduce a new feature—“safe npm”—that protects developers whenever they use
npm install. The feature transparently wraps the
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 inst, etc.
npm rm– which can actually install packages! (See the FAQ below for an explanation)
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.
To get started, install the Socket CLI by running
npm install -g @socketsecurity/cli . This adds a
socket command to your PATH.
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.
This type of protection is even more needed for commands like
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
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!
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.
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 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
For people wishing to avoid typing out
socket npm a shell alias like the following in your
alias npm="socket-npm" alias npx="socket-npx"
zsh autocompletions you may wish to add the following as well:
compdef _npm socket-npm
bash autocompletions you may wish to add the following as well:
$(complete -p npm | sed 's/npm$/socket-npm/')
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.
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:
We hope to gather feedback and expand the capabilities to support the full range of Socket configuration options and rules in a future release.
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!
npm uninstallever 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
firstname.lastname@example.org it will constrain
bar to be on
1.1.x but a different dependency
baz might depend on on
email@example.com which constrains
bar to any version
firstname.lastname@example.org exists it would be available to use if
foo is removed from the
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.
socket npm install foo?
Same reason as above.
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
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!
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
Socket provides an introspective on code signing in relation to the supply chain incident from SolarWinds.
The Socket blog now offers both full content Atom and JSON feeds which let you subscribe to all future Socket blog posts.
The Socket GitHub app now runs Project Health Reports on the default branch instead of in pull requests.