Typosquatting Package Attacks Explained

Typosquatting Package Attacks Explained

Written by

in

A typosquatting attack is one of the cheapest tricks in the software supply chain. An attacker publishes a package whose name is a near miss of a popular one, then waits for a developer to mistype the install command and pull the malicious copy instead. This post explains how the trick works in package registries, what the fake package does once it lands, how it differs from two lookalike attacks, and how to defend your builds.

How a typosquatting attack works

Package registries like npm, PyPI, and RubyGems let anyone publish a package under almost any unused name. That openness is the whole point, and it is also the opening. An attacker studies which packages are downloaded millions of times, then registers a name that sits one keystroke away from the real one.

The near miss usually takes one of these shapes:

  • A swapped or doubled letter. The real package is reqwest-client and the fake is reqewst-client.
  • A missing character. The real one is colorstream and the fake is colorstram.
  • A - swapped for a _. The real one is data_loader and the fake is data-loader.
  • A common misspelling. The real one is serialize-fast and the fake is serialise-fast.

Say your project depends on a real, popular package called fastparse. You are typing quickly and run this:

npm install fatsparse

If an attacker has already registered fatsparse, your build just downloaded their code and ran whatever they told it to run. No exploit, no clever payload delivery. You typed it in yourself.

What the malicious package does once installed

Getting the package onto the machine is only step one. The attacker still needs their code to run. In most registries the fastest way is an install hook. npm packages can declare lifecycle scripts in package.json, and a postinstall script runs automatically the moment the package is installed.

{
  "name": "fatsparse",
  "version": "1.0.0",
  "scripts": {
    "postinstall": "node ./collect.js"
  }
}

That single line is enough. When collect.js runs, it has the same access your terminal does. A real attack script tends to do a few quiet things at once:

  • Read environment variables and files that hold tokens, such as .npmrc, .env, or cloud credentials on disk.
  • Send them to a server the attacker controls, often inside a normal looking HTTPS request so it blends in with other traffic.
  • Print the expected output so the install looks ordinary and nobody stops to read it.

Because the code runs during install, it fires on a laptop, on a build server, and inside continuous integration. A stolen token from a build pipeline is often worth far more than one from a single developer, since it can push new releases or reach production systems. For a closer look at how these hooks are abused, read our teardown on malicious npm lifecycle scripts.

The typosquatter does not break into anything. They register a name, wait for a typo, and let your own install command do the rest.

Typosquatting is not dependency confusion, and not slopsquatting

Three supply chain tricks get lumped together. They share a goal, tricking you into installing attacker code, but the mechanism is different for each, and the defense differs too.

Dependency confusion

Dependency confusion targets companies that publish private internal packages. Suppose your team has a private package named acme-internal-auth that only exists on your registry. An attacker registers that exact name on the public registry with a higher version number. When your installer resolves the package, it sees the public version, decides it is newer, and pulls the attacker copy instead of yours. The name is not a typo. It is identical. What the attacker abuses is your resolver picking the wrong source. We cover the fix in detail in dependency confusion attack.

Slopsquatting

Slopsquatting is newer and rides on AI coding tools. When you ask a model for code, it sometimes invents a package name that does not exist, stated with full confidence. An attacker watches for these hallucinated names, registers the popular ones, and fills them with malicious code. The next developer who trusts the AI suggestion and runs pip install on the invented name gets the attacker package. Here nobody made a typo and no private name was shadowed. The bad name came from the model. We go deeper in slopsquatting attack.

The short way to keep them straight: typosquatting exploits your fingers, dependency confusion exploits your resolver, and slopsquatting exploits your AI assistant.

How to defend against a typosquatting attack

No single control stops every case, so layer a few. Each one closes a different gap.

Pin exact versions and commit a lockfile

A lockfile records the exact version and content hash of every package your project resolved. When a teammate or a build server installs, it verifies each package against that hash. If a name resolves to something different, the install fails instead of running new code. Commit package-lock.json, yarn.lock, poetry.lock, or your ecosystem’s equivalent, and treat any change to it as something to review, not to rubber stamp.

Read the name before you install

Most typosquats die if someone reads the name slowly. Before adding a dependency, check the spelling against the official docs or the project’s own repository. Copy the exact name from a trusted source rather than typing it from memory. When you paste an install command from a blog post or a chat, look at every character in the package name.

Use a private registry or an allowlist

A private registry or proxy sits between your builds and the public one. You approve packages once, and only approved names install. A new name that nobody vetted cannot enter the build at all, which stops both a fresh typosquat and a dependency confusion push. For smaller teams, even a written allowlist of approved packages, checked in code review, raises the bar.

Review every new dependency

Treat adding a dependency like merging code, because that is what it is. In code review, ask a few questions about any new name. How old is the package? How many other projects use it? Does it declare an install script, and if so, what does it do? A package published last week with almost no downloads, a name one letter off a famous one, and a postinstall hook is a stack of warning signs.

Scan for lookalikes

The signals above can be checked automatically. Good scanning flags a dependency that is brand new, has low reputation, declares install scripts, and closely resembles the name of a far more popular package. Any one of those can be innocent. Together they are the exact shape of a typosquat, and a scanner that reasons about the combination catches it before it reaches your lockfile. Browse more of these breakdowns in our deep dives.

A worked example, start to finish

Put it together with an invented case. A team uses a real, popular logging package called quicklog. An attacker registers qucklog, copies the real package’s code so it works normally, and adds a postinstall script that reads .npmrc and posts the auth token to their server. A developer, moving fast, runs npm install qucklog. The install prints the usual lines and the app still works, so nothing looks wrong. In the background, the token is gone. With a committed lockfile and a review step, that install never happens. The name mismatch is caught in review, or the missing hash stops the install, or the private registry refuses the unknown name. Defense in depth is what turns a one keystroke mistake into a non event.

This class of attack survives because it hides inside a normal action and never triggers a classic alarm. That is the kind of assumption an attacker abuses, and testing those assumptions is the work UnboundCompute is built to do. Read how we think about it on our about page.

Frequently asked questions

What is a typosquatting attack in package registries?

It is when an attacker publishes a package whose name is a near miss of a popular one, such as a swapped letter, a missing character, or a hyphen where the real name uses an underscore. When a developer mistypes the install command, the registry serves the attacker copy, which usually runs code on install to steal tokens or credentials.

How is typosquatting different from dependency confusion?

Typosquatting relies on a typo: the fake name is a misspelling of a real public package. Dependency confusion uses an identical name to a private internal package, published to the public registry with a higher version number so your resolver picks the public attacker copy over your private one. One exploits your fingers, the other exploits your resolver.

What does a malicious typosquatted package actually do?

Most rely on an install hook, such as an npm postinstall script, that runs automatically during installation. The script reads environment variables and files like .npmrc or .env, sends any tokens it finds to the attacker, and prints normal looking output so the install seems fine. Because it runs on build servers too, it can steal pipeline credentials.

How do I protect my project from typosquatting?

Layer a few controls: commit a lockfile so installs verify each package by content hash, copy package names from official docs instead of typing them, use a private registry or allowlist so only approved names install, review every new dependency in code review, and scan for a brand new low reputation package that closely resembles a popular name and declares install scripts.


Put an autonomous researcher on your own systems

UnboundCompute is an autonomous security researcher that reasons about how an application fits together and proves the access control and injection bugs it finds. We are opening a small number of founding design partner seats: private early access pointed at a staging target you choose, and a say in what it looks for. If your team ships software worth pressure testing, apply to the design partner program.