Lookalike name

Check P10 · provenance family · severity HIGH · automatic · one of the 12 npm and PyPI package checks

Maps to OWASP LLM03 OWASP LLM09 ATLAS AML.T0074 ATLAS AML.T0060 A name built to be mistaken for another, which is masquerading when a person reads it and a hallucinated entity when a model does.

The question this check asks: is this name one keystroke away from a package everyone uses? A typosquat lives on the mistake: a letter changed, dropped or added, a scope dropped or added.

Why it matters

The typosquat is the oldest registry attack and still the cheapest: publish a near-miss of a popular name and wait for someone to mistype it. An agent writing a command line makes the same mistakes and a few of its own — a plausible name for a package that does not exist is something an attacker can register first. The defence is to compare the name with the names people actually mean.

How RepoGates scores it

The name is compared with RepoGates' vendored lists of the most-used packages on each registry, refreshed weekly with a reviewed diff. A package on the list is never a lookalike. Otherwise, when both names are at least 5 characters long, a name one edit from a listed name — one letter added, removed or changed — or the same name under a different npm scope, is pkg-lookalike:<name>: HIGH and 18 points on a new package (first published less than 90 days ago) and a note at 0 points on an established one. The finding names the popular package. Names are compared as the registry compares them (case-folded; on PyPI _ and . read as -).

False positives we know about

A real package with a near-name. Short popular names have neighbours that are perfectly honest packages, which is why names under five characters are not compared and an established package is a note: a lookalike that has been on the registry for months, with its own history, is far more likely to be a coincidence than a trap. A new one is a warning, naming the package it resembles.

What this check does not cover

A lookalike of a package not on the list. The lists are the most-used names on each registry; a near-name of something less popular is not compared. A lookalike two edits away is not this check's shape, and two swapped letters count as two edits: lodahs is not one edit from lodash, and it is OSV's report on it (MAL-2025-25502) that P1 reads. A name built from a word swap or a suffix is not compared either. Names under five characters are not compared. The package's code is not read.

Scope, the same on every page of this roster: RepoGates does not see git clone, package managers or curl — outside Claude Code with the RepoGates plugin, whose hook refuses a clone or install that names a blocked repository on the command line, before it runs. The hook sees Bash tool calls in that one client and nothing else; a package named on the line (npm install express, pip install flask, npx, npm create) is judged by its own verdict under this roster, its declared repository riding along. Direct dependencies named on the command line only; transitive dependencies and lockfiles are not resolved. A package added by editing package.json or requirements.txt and installed later is not a line the hook judges. Edit and Write are read for one thing only — an API key about to be saved — checked on the machine and never sent; that guard asks, it never denies. This roster reads what npmjs.org and pypi.org publish about a package — its record, its release history, its declared repository — and never the package's code or what it installs after it. A registry other than those two (a --registry or --index-url on the line) is asked about, not assessed. A package the registry no longer serves is not assessed, never a pass. A PASS means nothing matched on what was read.

Check it yourself

Read the name you are about to install letter by letter against the package you meant, and look at both on the registry:

npm view NAME name time.created repository
npm view INTENDED name time.created repository

Questions

What counts as a lookalike? A name one edit from a name on RepoGates' list of the most-used packages on that registry — one letter added, removed or changed — or the same name under a different npm scope, when both names are at least five characters long. A package that is itself on the list is never a lookalike.

Why is an established lookalike only a note? Because short and common names have honest neighbours, and a near-name that has been on the registry for 90 days or more has a history of its own. A new one is a high finding that names the package it resembles.

Where do the lists of popular packages come from? From public lists of the most-used npm and PyPI packages, vendored into RepoGates and refreshed weekly with a diff a person reviews. A publisher cannot add their own package to them.

Related checks

P1 Known malicious · P4 Name matches its source · C4 Fork and lookalike · V4 Lookalike publisher or name.

Add RepoGates to Chrome Pricing

Sources for this page: the thresholds and weights from the product's own roster and scoring tables; the OSV id for lodahs as read on 29 October 2026; the edit-distance rule from the check's own code.