Safeguard
Open Source Security

Anatomy of a Typosquatting Campaign: How Attackers Pick T...

Real typosquatting campaigns follow a repeatable playbook: target selection, edit-distance tricks, and install-time payloads. Here's how attackers actually pick their targets.

Vikram Iyer
Security Researcher
7 min read

In March 2017, a package called crossenv appeared on npm — one keystroke away from the legitimate cross-env, a tool installed by thousands of JavaScript projects. It exfiltrated environment variables, including API keys and database credentials, to a remote server. It wasn't a fluke. It was a proof of concept for a technique that has since scaled into an industrial-grade attack pattern. In 2023 alone, security researchers tracked hundreds of typosquatted packages across PyPI and npm as part of a single campaign known as W4SP Stealer, and Sonatype's annual supply chain report recorded a record-breaking count of malicious open source packages, the majority following predictable naming tricks.

Typosquatting looks trivial from the outside — just misspell a popular package and wait. But a real typosquatting package attack analysis shows the targeting is anything but random. Attackers choose names, ecosystems, and payloads using a repeatable playbook. Understanding that playbook is the first step to defending against it.

What Makes a Package Name a Good Typosquatting Target?

The best targets are packages with high download volume, short or visually ambiguous names, and human operators who type them from memory dozens of times a day. requests (PyPI), lodash (npm), colorama (PyPI), and discord.js (npm) fit this profile perfectly: each sees tens of millions of downloads and each has a name simple enough that a developer types it without looking, especially inside CI scripts, Dockerfiles, or pip install one-liners copied from Stack Overflow. Attackers cross-reference registry download rankings and dependency graphs from projects like libraries.io to find packages that sit at the intersection of "widely used" and "rarely double-checked."

Length matters too. A one-character swap in a four-letter name like ua-parser-js is far more forgiving to a typo than the same swap in a twenty-character name, because the ratio of altered characters to total characters is what determines whether the mistake looks plausible. This is why attackers gravitate toward core utility libraries — colorama, six, yaml, jellyfish — over long, compound package names that developers tend to type carefully or paste from documentation.

Which Typo Patterns Do Attackers Actually Use?

The dominant pattern is single-edit-distance substitution, meaning the malicious name differs from the real one by exactly one character insertion, deletion, transposition, or swap. The 2021 PyPI package jeIlyfish is the textbook case: a capital "I" replacing the lowercase "l" in jellyfish, a difference invisible in most sans-serif fonts and terminal outputs. electorn for electron and python3-dateutil for python-dateutil follow the same logic — transposition and insertion errors that mirror actual human typing mistakes rather than random string mutation.

A second pattern, combosquatting, skips character-level tricks entirely and instead appends or prepends common qualifier words: -official, -utils, -cli, -js, or a company name. Because npm and PyPI don't reserve name variants for legitimate maintainers, discord.js-selfbot-v14-style names have been used repeatedly to impersonate the real discord.js ecosystem and harvest authentication tokens from bots and desktop clients.

A third, more advanced pattern is scope or namespace confusion — publishing an unscoped package that mirrors a scoped one (or vice versa), such as a public babel-core clone shaped to be confused with @babel/core. This overlaps with dependency confusion attacks, where a public package is given the same name as an internal, private package but with a higher version number, tricking package managers configured to prefer the highest version across registries. Security researcher Alex Birsan demonstrated this against more than 35 companies, including Apple, Microsoft, and PayPal, in February 2021.

Do Attackers Target npm and PyPI the Same Way?

No — the two ecosystems reward slightly different tactics because of how their tooling resolves names. PyPI has historically had looser namespace controls and a large base of data science and ML practitioners who install packages by hand in notebooks, making it fertile ground for single-character substitutions on package names like numpy, pandas, and torch (the 2022 torchtriton incident involved a similarly-named malicious package that PyTorch itself had to explicitly warn about). The W4SP Stealer campaign, tracked through 2022 and 2023, published waves of packages with names like importantpackage, 10Cent10, and typo variants of colorama and requests, each carrying an obfuscated payload that stole Discord tokens, browser credentials, and crypto wallet data.

npm, by contrast, sees more combosquatting and dependency-confusion-style attacks because of its deep, transitive dependency trees — a single npm install can pull in hundreds of indirect packages, any one of which is a viable insertion point. Attackers targeting npm often go after build tooling and framework ecosystems (React, Vue, Discord bots) rather than single utility functions, because a compromised build-time dependency executes during npm install via lifecycle scripts like postinstall, giving the attacker code execution before a human ever reviews the package.

How Do Attackers Turn a Typosquat Into a Working Payload?

Almost universally, the payload runs automatically at install time rather than waiting for the package to be imported and used. On npm, this means abusing postinstall or preinstall scripts defined in package.json, which execute the moment the package is downloaded — no code needs to be called, no function needs to be invoked. On PyPI, the equivalent trick is embedding malicious logic inside setup.py, which runs during the build step of pip install, again before the developer has written a single line of code that references the package.

The payloads themselves have matured. Early typosquats like colourama (2017) sent Windows clipboard contents to a remote server. By 2022–2023, typosquat payloads in campaigns like W4SP and the "PyPI Discord token stealer wave" were fetching a second-stage script from a remote host, decoding it with base64 or Fernet encryption to evade static scanners, and exfiltrating browser-stored passwords, Discord tokens, SSH keys, and environment variables in a single automated sweep — all within seconds of pip install completing.

What Happens After Someone Installs the Wrong Package?

The blast radius is rarely limited to one developer's laptop. Because the malicious install typically runs with the same privileges as the developer's shell, it can read SSH keys, cloud credential files (~/.aws/credentials, ~/.config/gcloud), and CI/CD secrets injected as environment variables — meaning a single mistyped pip install requessts on a build server can leak production deployment keys, not just local test data. In CI pipelines specifically, the attacker gets a repeatable trigger: every build re-runs the install and re-executes the payload, giving attackers a window that can span weeks between when a typosquat is published and when it's finally flagged and removed by registry maintainers.

Because both npm and PyPI allow near-instant publishing with minimal identity verification, the time-to-takedown is the real variable that determines damage. Some campaigns are caught within hours by automated scanners; others, like slower-burn combosquats sitting quietly in a long dependency chain, have persisted for months before discovery, continuing to collect credentials from every fresh install in that window.

How Safeguard Helps

Typosquatting attacks succeed because they exploit a gap between what a developer types and what actually gets resolved and installed — a gap that manual code review rarely closes, since the malicious code often runs before any human reads it. Safeguard closes that gap at the point of resolution, not after the fact.

Safeguard continuously analyzes your declared dependencies against known-good package identities, flagging near-matches, edit-distance anomalies, and newly published packages with suspiciously similar names to your existing dependency tree before they're pulled into a build. It inspects install-time behavior — including postinstall, preinstall, and setup.py build hooks — to catch payloads that try to execute network calls, read credential files, or decode obfuscated strings during installation, the exact mechanism typosquats rely on to avoid ever being imported or reviewed.

Because dependency confusion and combosquatting attacks specifically target the gap between internal and public registries, Safeguard also maps your organization's internal package names against public registry namespaces, alerting you if a public package that could shadow an internal one is published, closing the exact vector Alex Birsan used against dozens of major companies. And because the real damage from a successful typosquat comes from what it accesses after execution, Safeguard's runtime and CI/CD integration monitors for anomalous credential access and outbound network activity immediately following a new package install — shrinking the detection window from weeks to minutes.

A typosquatting package attack analysis of any real campaign leads to the same conclusion: attackers are betting that speed and habit will beat scrutiny. Safeguard is built to make sure that bet doesn't pay off.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.