
Dependency Confusion: How Attackers Poison Your Build | Blog | Endor Labs
Endor Labs explainer breaking down three "tree poisoning" techniques in the open-source dependency tree: dependency confusion (public package impersonating a private one, exploiting "highest version wins" resolver logic, as in Alex Birsan's 2021 research against 35+ companies and PyTorch's 2022 torchtriton nightly-build compromise), typosquatting/combosquatting (human-error-driven lookalike package names, extended by AI-invented "slopsquatting"), and package poisoning/hijacking (maintainer account takeover or handoff abuse, as with event-stream in 2018, the XZ Utils backdoor in 2024, and the Shai-Hulud npm worm). It closes with concrete defenses: reserving package namespaces, pinning private registries, lockfiles/checksum verification, scrubbing internal names from public sources, and package firewalls with behavioral malware detection.
What to do
The page's payload is a set of per-ecosystem configuration specifics the summary flattens into "pinned private registries" and "lockfiles." Reproduced as stated:
- Reserve names/namespaces. Claim internal package names on public registries before an attacker does, and use scoped packages like
@company/packageso a public name cannot shadow a private one. - Pin private sources, per package manager:
- npm — scope a registry in
.npmrc. - pip — use
index-urlalone and dropextra-index-url(the extra index is what lets resolution fall through to the public registry). - NuGet — use
packageSourceMapping. - Lockfiles + version pinning. Commit
package-lock.json,yarn.lock, or a hashedrequirements.txt; verify checksums; avoid floatinglatest. - Remove public mentions of internal names. Reconnaissance is step one of dependency confusion — keep internal names out of public repos, configs, and CI logs.
Why the mechanism, not a bug
Dependency confusion is a design flaw, not a vulnerability: the resolver checks public and private registries together and picks the highest version. An attacker who learns an internal name publishes a public package under it with a high version, and the build resolves to the attacker's copy. On install, preinstall/postinstall scripts run — reading env vars, hitting cloud metadata endpoints, exfiltrating secrets, establishing persistence. This framing tells you why the extra-index-url removal and version pinning are the fixes that matter: they attack the "both registries, highest wins" convergence directly.
flowchart TD
A[Internal name leaked in public repo/CI log] --> B[Attacker publishes public pkg, high version]
B --> C{Resolver checks<br/>public + private}
C -->|highest version wins| D[Malicious pkg installed]
D --> E[install scripts: steal secrets, persist]
C -.->|index-url only,<br/>scoped @company/pkg| F[Private version resolves]
A -.->|scrub internal names| CThe diagram shows the two places a defense cuts the chain: scrubbing names removes the reconnaissance input, and single-source resolution (index-url alone, scoped packages) removes the fork the resolver would otherwise take.
Worth knowing
Two data points the summary omits that size the problem: Endor Labs estimates 70–90% of application code is open-source, and 95% of vulnerability risk lives in transitive dependencies — the roots you never picked, which is exactly where poisoning propagates upward.
Note the page's defense list is truncated mid-item ("Use a p…"), so at least one recommended control is not captured here.
Organisations named here
- Alex Birsan
- event-stream
- Shai-Hulud
- slopsquatting
- torchtriton
- xz-utils
Technologies named here
- Endor Labs package firewall
- lodash
- npm
- PyPI
- pip
- PyTorch nightly build
- NuGet
- package-lock.json / yarn.lock / hashed requirements.txt
- XZ Utils
- Apple, Microsoft, PayPal
- PyTorch
- Endor Labs
Techniques named here
- Dependency confusion
- Typosquatting
- Combosquatting
- Slopsquatting
- Package poisoning
- Account takeover / maintainer hijacking
- Reconnaissance for internal package names
- Malicious preinstall/postinstall scripts
- DNS callback proof-of-concept
Threat actors named here
- torchtriton malicious package
- event-stream malicious dependency
- XZ Utils backdoor
- Shai-Hulud worm
- protestware
- slopsquatting
Related in Supply Chain


