Safeguard
Vulnerability Analysis

Typosquatting in open source package registries explained

Typosquatting hides malware behind a one-character package name typo. Learn how it works, real incidents, and how to detect it before your build runs.

Nayan Dey
Security Researcher
7 min read

Typosquatting in a package registry means publishing a malicious package under a name that is one keystroke away from a popular legitimate one — crossenv instead of cross-env, colourama instead of colorama, python3-dateutil instead of python-dateutil — and waiting for a developer's typo, a broken tab-complete, or a copy-pasted install command to pull it in instead. It is one of the cheapest attacks in the software supply chain: no compromised maintainer account, no CI pipeline breach, just a name and a publish command. In February 2020, RubyGems removed 725 such packages in a single sweep. In 2023, Sonatype identified 245,032 malicious open source packages, up nearly 200% year over year, and a large share relied on name confusion rather than any technical exploit. This post explains how the attack works, why registries still can't fully stop it, and how to catch it before it reaches a build.

What Is Typosquatting in an Open Source Package Registry?

Typosquatting is the practice of registering a package name that closely resembles a popular, trusted package, so that developers who mistype, misremember, or misread the real name install the attacker's version instead. It exploits human input error rather than a code vulnerability — the malicious package itself can be perfectly "secure" in the traditional sense while still executing arbitrary code the moment it's installed, because npm, PyPI, RubyGems, and most other registries run install-time scripts (postinstall hooks, setup.py) by default.

The technique predates modern package managers — it's the same idea as gooogle.com — but it's far more damaging in a registry context because a single pip install or npm install runs code immediately and often with a developer's or CI system's full local privileges. A 2017 PyPI experiment by researcher Nikolai Tschacher made the mechanics concrete: he uploaded 20 typosquatted clones of common packages (variants of names like bs4 and pyyaml) purely to measure exposure, with no payload. Within a few months those decoy packages had logged more than 45,000 downloads, none of which involved any exploit at all — just people typing the wrong name.

How Do Attackers Pick Which Names to Squat?

Attackers target names with the highest chance of an accidental match combined with the highest download volume, using a small, repeatable set of string mutations: character omission (lodashlodahs), character swap, doubled letters, hyphen/underscore confusion (cross-envcrossenv), and common misspellings of technical terms. The 2017 crossenv incident is the canonical npm example — it squatted cross-env, a legitimately popular package for setting environment variables across platforms, and once installed it scraped npm credentials and environment secrets from CI environments before publishing the harvested data back to the attacker.

Cryptocurrency and wallet-adjacent libraries are a favorite target because the payoff is direct: the RubyGems campaign removed in February 2020 consisted of gems typosquatting legitimate crypto-related gem names, and once installed they hijacked the clipboard to silently replace any copied cryptocurrency wallet address with an attacker-controlled one. Naming a package after a hyphen variant, a pluralization, or a common abbreviation of something with millions of weekly downloads is a low-effort, high-reach strategy, and attackers frequently register a dozen variants of the same target name at once to widen the net.

What Do Real Typosquatting Incidents Actually Look Like?

Real incidents follow a consistent pattern: publish a near-identical name, add a plausible README, ship a payload in an install hook, and let download counts do the rest before the registry notices. colourama, a British-spelling typosquat of the widely used colorama PyPI package, was caught after it was found bundling a clipboard hijacker that swapped copied cryptocurrency addresses — the same tactic as the RubyGems campaign, on a different registry, discovered separately in 2022. electron-native-notify, published to npm in September 2021, mimicked naming conventions from the legitimate Electron ecosystem and shipped a remote-access trojan that exfiltrated Discord tokens and browser credentials.

What ties these together operationally is not sophistication — none required a zero-day or a compromised build system — but timing and volume. Typosquats are typically discovered days to weeks after publication, during which any CI job, container build, or local npm install that hits the wrong name has already executed the payload. Sonatype's 2023 State of the Software Supply Chain report put the scale in context: 245,032 malicious packages identified that year alone, a near-200% increase over 2022, with name-confusion attacks (typosquatting plus "brandjacking" and dependency confusion) forming one of the largest categories tracked.

Why Can't Registries Just Block Similar Names?

Registries can't fully block similar names because uniqueness checks only catch exact duplicates, and legitimate projects also need short, generic, and abbreviated names that inevitably collide with near-misses of other legitimate projects. npm, PyPI, and RubyGems all allow any unclaimed string as a package name on a first-come basis; there is no built-in Levenshtein-distance check against the top N most-downloaded packages at publish time on any major public registry as of this writing, though PyPI has added post-publication malware scanning (via tools like PyPI's own automated checks and third-party reporting integrations) since the 2022 wave of cryptomining and clipboard-hijacking incidents.

The deeper problem is that blocking near-matches proactively would also block a large volume of legitimate publishing — scoped packages, forks, language ports, and abbreviations are all "close" to something else by design. So registries default to reactive takedown: something gets reported or flagged by automated heuristics (unusual install scripts, obfuscated code, sudden spikes tied to a name resembling a top-1000 package), a maintainer or researcher confirms it, and the package is pulled — usually after it has already accumulated real installs. The RubyGems 725-package removal and the Sonatype 245,032-package figure are both counts of packages caught after the fact, not prevented in advance.

How Can Security Teams Catch Typosquats Before They Reach a Build?

Security teams catch typosquats before a build by pinning exact package versions with lockfiles, generating and diffing a software bill of materials (SBOM) on every build, and scanning new or changed dependencies against known-malicious and name-similarity databases rather than trusting registry search results or a developer's memory. Lockfile discipline alone (package-lock.json, poetry.lock, Gemfile.lock committed and enforced in CI) blocks the most common failure mode — an unpinned install resolving to a name that was typed wrong once and never caught.

Beyond pinning, effective detection combines three signals: install-time script inspection (flagging postinstall/preinstall hooks in newly added dependencies), publish-recency and maintainer-reputation checks (a package published days ago with no history is a materially different risk than one with three years of releases), and automated edit-distance comparison of every new dependency name against your organization's top-used and top-industry package lists. None of these require manual review of every dependency — they're exactly the kind of check that belongs in CI, gating a merge rather than relying on a developer reading every package.json diff by eye.

How Safeguard Helps

Safeguard's Griffin AI continuously screens newly added and updated dependencies for name-similarity, suspicious install hooks, and publish-history anomalies consistent with typosquatting, flagging risky packages before they land in a merged branch rather than after a download count climbs. Safeguard generates and ingests SBOMs across your build pipeline so every dependency — including transitive ones pulled in by a typosquatted parent package — is inventoried and diffable release over release, not just the top-level packages your team deliberately chose. Reachability analysis then determines whether a flagged package's code paths are actually exercised by your application, so security teams can triage a suspected typosquat by real exploitability instead of chasing every look-alike name in the tree. When a match is confirmed, Safeguard can open an auto-fix pull request that swaps the typosquatted dependency for the legitimate package and pins the corrected version, closing the gap between detection and remediation in minutes instead of the days or weeks these packages typically go unnoticed in the wild.

Never miss an update

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