Safeguard
Concepts

What is Typo-Squatting Detection

Typo-squatting detection identifies malicious packages named one keystroke away from real ones — requets instead of requests — before they reach your build.

Jonas Meyer
Site Reliability Engineer
6 min read

Typo-squatting detection is the automated identification of packages whose names are deliberately confusable with popular ones — requets for requests, lodahs for lodash, python-dateutil vs python3-dateutil — so that a single mistyped install command or a hallucinated dependency name delivers attacker-controlled code instead of the library you meant. The attack works because package installation is a name-based trust decision with no second factor: pip install gives whoever registered the string, and registries operate first-come-first-served on names.

It's a numbers game for attackers, and the numbers are good. requests sees hundreds of millions of downloads a month; if even 0.01% of manual installs fat-finger the name, a squatter collects thousands of executions of arbitrary code — because both npm and Python packaging support install-time hooks (preinstall scripts, setup.py) that run before you've imported anything.

What the attacks actually look like

A short history for calibration:

  • ctx and colourama (PyPI, 2018) — the second one squatting colorama, exfiltrating environment variables and AWS keys on install. The pattern hasn't changed since; only the payloads have.
  • The 2023–2024 npm crypto-stealer waves — hundreds of packages like noblox.js-proxy squatting noblox.js, shipping token grabbers aimed at game developers.
  • go-module-mirror BoltDB squat — a typosquatted Go module that carried a backdoor for roughly three years because the module proxy caches immutably; we did a full write-up in the boltdb typosquat post.
  • Slopsquatting (2024–2025) — the newest variant: LLM coding assistants hallucinate plausible-but-nonexistent package names at measurable rates (research across models put it near 20% of suggested packages in some ecosystems), and attackers register those names preemptively. Same mechanics, new discovery channel.

Related but distinct cousins: combosquatting (react-dom-router vs react-router-dom — real words, wrong order), namespace confusion (@types/lodahs), and dependency confusion, which exploits registry resolution order rather than human typing. Detection systems usually cover the whole family.

How detection engines decide a name is suspicious

No single signal is reliable; production detectors stack several:

SignalTechniqueExample
Name distanceDamerau-Levenshtein distance of 1–2 against a top-N popularity listlodahslodash (distance 1, transposition)
Keyboard adjacencyWeighted edits by physical key proximityrequeatsa sits next to s
Homoglyphs / confusablesUnicode skeleton comparison (UTS #39)раramiko with a Cyrillic р
Popularity asymmetryNew, near-zero-download package near a giant40 downloads sitting one edit from 300M/month
Metadata mimicryREADME/description copied from the targetIdentical docs, different install hook
BehavioralInstall-script analysis: network calls, env reads, obfuscationpreinstall curl-piping to a paste site

The name-distance layer alone drowns in false positives — legitimate forks, regional variants, and coincidences are everywhere (color and colors are both real). That's why the popularity asymmetry and behavioral layers matter: a name one edit from express is interesting; a name one edit from express, registered last Tuesday, with an obfuscated postinstall that reads ~/.npmrc and POSTs somewhere, is a verdict.

Registries run their own versions of this — npm has blocked new names that are too similar to existing popular packages since 2017 (the crossenv incident), and PyPI added Unicode normalization rules — but registry-side filtering is a floor, not a guarantee. The steady cadence of malicious-package reports from OSV and vendor research feeds demonstrates the leak rate.

Wiring detection into your pipeline

Detection you don't enforce is a threat-intel newsletter. Practical enforcement points, in order of value per effort:

  1. PR-time dependency review. Any diff to package.json, requirements.txt, go.mod, or a lockfile triggers a check of new names against a squatting detector and malicious-package feeds (OSV.dev aggregates several). New-dependency review is rare enough that a human check on flagged names doesn't slow anyone down.
  2. Registry proxy rules. If installs flow through an Artifactory/Nexus/Verdaccio proxy, block first-fetch of packages flagged by your detector, and quarantine anything younger than 72 hours. Most malicious packages are removed within two days of publication; a cooling-off window skips the exposure entirely.
  3. Lockfile scanning in CI. Scan the resolved tree, not just the manifest — squats arrive transitively too. This is where SCA tooling earns its place: Safeguard's malicious-package detection runs name-similarity and install-script behavioral checks against every new package entering the lockfile, which catches the class rather than the known list.
  4. Guardrails for AI-generated code. If your org uses coding assistants, add a CI rule: any dependency that didn't exist on the registry 30 days ago, or has under some threshold of weekly downloads, requires explicit human approval. This one rule neutralizes most slopsquatting risk.

One habit worth building at the individual level: copy-paste install commands from the project's official README instead of typing them. Boring advice; it's also how the majority of manual-install squats actually succeed.

What detection can't do

A well-run typosquatting program still doesn't cover: compromise of the legitimate package (account takeover — different attack, different controls), malicious code added in version 4.2.1 of a package you've depended on for years, or squats in ecosystems you don't scan (Docker Hub images and GitHub Actions get squatted too, and most tooling focuses on language registries). Treat name-based detection as one layer of package vetting, alongside pinning, provenance verification, and install-script sandboxing (npm install --ignore-scripts as a default is unreasonably effective).

Frequently asked questions

How common is typo-squatting really?

Continuously — researchers and registry teams remove thousands of malicious lookalike packages per year across npm and PyPI, and every large-scale study finds active campaigns. Most individual packages get few downloads, but the tail events (a squat trending or surviving months) are what the controls are priced against.

Does dependency pinning protect against typo-squatting?

Mostly no. Pinning guarantees you keep getting the package you resolved — including a squatted one if that's what entered the lockfile. Pinning prevents drift; typosquatting detection prevents the wrong name from entering in the first place. You need both.

Are private/internal package names at risk?

Yes, via the adjacent dependency-confusion attack: an attacker registers your internal package's name (or a near-variant) on the public registry. The defenses are registry scoping and resolution-order controls rather than name-distance detection, but mature tools check both patterns together.

Can I check a single package name quickly?

Reasonable quick checks: the package's download count and age on npmjs.com or PyPI, whether the repository link actually points to the project it claims, and OSV.dev for known-malicious flags. If a "popular" library has 60 weekly downloads and a repo link to an empty GitHub account, you have your answer.

Never miss an update

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