Typosquatting

Typosquatting

What Is Typosquatting?

The technique originated in domain registration, buying gooogle.com to catch traffic from mistyped URLs, and transferred to package registries essentially unchanged. Registries are open, names are first-come, and adjacent names are free.

A typosquatted package name exploits one of a few predictable patterns: a transposed character, a doubled or dropped letter, a hyphen where the original uses none, a singular where the original is plural, or a scoped package published unscoped. Each is a plausible typing error, and each is a distinct registry namespace.

The malicious package then does one of two things. It either functions as a stub that does nothing visible while its install script runs the payload, or, more effectively, it wraps and re-exports the legitimate package so the developer's code works perfectly and nothing seems wrong. The second approach can persist for months.

The payload varies but the goal rarely does: harvest credentials from the environment, establish persistence in CI, or open a path for a later stage. Install-time execution means the payload runs before any human reviews a line of the package.

How Typosquatting Targets Software Package Ecosystems

Every major registry shares the properties that make this viable: open publishing, name-based resolution, and install-time code execution.

Character-Level Name Proximity

Attackers enumerate plausible misspellings of high-download packages programmatically, transpositions, omissions, doubled characters, adjacent-key substitutions. The candidate list for any popular package name is mechanical to generate and cheap to register.

Scope and Namespace Confusion

A scoped package like @org/utils has an unscoped sibling namespace sitting empty. Registering utils-org or org-utils catches developers who half-remember the name or copy it from documentation that dropped the scope.

Copy-Paste Propagation

A single bad install command in a tutorial, Stack Overflow answer, or AI-generated code snippet delivers victims without any typing error at all. The developer copies correctly, the source was wrong. This vector has grown as generated code suggests package names that sound right.

Install-Time Execution

Lifecycle scripts run automatically on install. The gap between typing a wrong name and executing attacker code is a single command with no review step in between, and it happens on developer machines and CI runners with equal ease.

Functional Camouflage

By re-exporting the real package, the squat behaves correctly. Tests pass, the build succeeds, the feature works. Nothing prompts investigation, so the package persists in the lockfile and propagates to every environment that installs from it.

Typosquatting vs. Dependency Confusion: The Difference

Both deliver a malicious package under a name the developer believes is legitimate, but the mechanism is entirely different, and so is the defence.

Typosquatting vs. Dependency Confusion

  • Trigger: Typosquatting is triggered when a developer types or copies a wrong name; Dependency Confusion happens when the resolver picks the wrong source for a right name.
  • Name used: Typosquatting relies on a name similar to the real package; Dependency Confusion uses a name identical to an internal package.
  • Exploits: Typosquatting exploits human error; Dependency Confusion exploits resolution precedence rules.
  • Requires: Typosquatting needs nothing but an open registry; Dependency Confusion requires knowledge of internal package names.
  • Victim mistake: Typosquatting depends on a victim mistake (a typo or bad instruction); Dependency Confusion needs none, since the name is correct.
  • Primary defence: Typosquatting is countered with lockfiles, allowlists, and name review; Dependency Confusion is countered with scope reservation and registry precedence config.

How Typosquatting Packages Evade Standard Security Scanning

This is the part most programs get wrong. Scanners are built to answer whether a package has known vulnerabilities, and a typosquatted package has none, it is new, so nothing is known about it. The blind spot is structural rather than a tuning problem, and it shapes what container scanning best practices can and cannot cover.

No CVE Exists to Match Against

SCA tools compare package names and versions against vulnerability databases. A package published yesterday with no disclosure history matches nothing. The scan returns clean because the question it asks, does this have known flaws, has the answer no.

The Package Is Not Vulnerable, It Is Malicious

Vulnerability and malice are different properties. A vulnerable package has a bug an attacker can use. A malicious package is working as intended. Tools designed for the first category have no signal for the second.

Behaviour Only Manifests at Install

Static analysis of the published tarball may see obfuscated code, but the payload often fetches its real logic at install time. What is scanned and what executes are not the same artifact.

The Squat Inherits Legitimate Behaviour

When the malicious package re-exports the real one, functional testing and dependency review both see expected behaviour. The only anomaly is a name that looks nearly right in a lockfile nobody reads line by line.

Detection Requires Reputation, Not Signatures

What actually catches these is metadata: package age, download history, maintainer track record, name similarity to popular packages, and unexpected install scripts. That is a different tool category from a CVE scanner, and most pipelines run only the latter.

How to Reduce Exposure to Typosquatting in Your Dependency Workflow

The controls that work are boring, and they work because they remove the moment of human judgement rather than trying to improve it.

Deterministic Installs from Lockfiles

Commit lockfiles and install with npm ci or the equivalent. A typo enters the lockfile once, in a reviewed pull request, not silently on every CI run. This narrows the attack to a single reviewable moment.

A Private Registry Proxy with an Allowlist

Route all installs through an internal proxy that only serves approved packages. A squat that is not in the allowlist cannot be installed regardless of what anyone types. This also defeats dependency confusion as a side effect.

Disable Install Scripts by Default

Run with --ignore-scripts and enable lifecycle scripts only for the specific packages that genuinely need them. Most do not. This removes the execution path that makes install-time payloads possible at all.

Review New Dependencies as Additions, Not Updates

Treat a new package name entering the lockfile as a change requiring the same scrutiny as new code. Check download counts, publish date, maintainer history, and repository links, the metadata that reveals a squat is available before install.

Reduce the Dependency Count Itself

Every dependency is a name that can be squatted and a maintainer who can be compromised. Pruning unused packages and preferring shallow trees shrinks the exposure directly, which is the same principle underlying best practices to manage Docker risk and vulnerabilities at the image layer.

FAQ

Can npm protect against typosquatting automatically?

Only partially. npm removes reported malicious packages and blocks some names that are too close to existing ones, but enforcement is reactive, a squat must be published and noticed first. The window between publication and takedown is where the damage happens. Registry policy reduces exposure; it does not eliminate the vector.

Is typosquatting the same as a supply chain attack?

Typosquatting is one type of supply chain attack. The category also covers maintainer account compromise, dependency confusion, malicious updates to legitimate packages, and build system compromise. What they share is delivering attacker code through a trusted distribution path rather than exploiting a flaw in the target.

How do you detect typosquatting in your dependency tree?

Compare installed package names against popular packages using edit-distance analysis, then review anything close but not identical. Combine with metadata checks: recent publish dates, low download counts, missing repository links, and unexpected install scripts. Tools for this are separate from CVE scanners, which will not flag these packages.

Ready to eliminate CVEs at the source?