Dependency Confusion: How a Researcher Hacked Apple and Microsoft

📋 Key Takeaways
  • What happened
  • How it worked
  • Impact and numbers
  • Timeline
  • Why it still matters in 2026
6 min read · 1,081 words
Educational & Ethical Use Only — This article is provided for educational and ethical cybersecurity research purposes only. The techniques described should only be used on systems you own or have explicit permission to test. Always follow responsible disclosure and the laws applicable to you. Mitigations are included so engineers can harden real systems.

In February 2021, security researcher Alex Birsan published a report that read like a magic trick: he had received bug bounties from more than 35 major companies — Apple, Microsoft, PayPal among them — for code that did nothing but exist. His technique, dependency confusion, exploited package-manager naming rules to get his own code auto-installed into corporate builds. Within weeks, copycats were doing it for extortion.

Quick Answer
Dependency confusion abuses how package managers resolve names between public registries (npm, PyPI, RubyGems) and internal/private registries. When an internal package name — say company-utils — has no public counterpart, an attacker registers that name on the public registry. Build systems that check public sources “for completeness” then pull the attacker’s higher-versioned package and execute its install hooks inside the corporate network. Birsan’s February 2021 writeup demonstrated it against 35+ organizations; copycats added ransom notes to the payload. The durable fix is boring: registry namespace policy, pinning, and never letting builds reach public registries for internal names.

What happened

Birsan’s research began where much supply-chain research does: someone else’s disclosure. After the November 2020 awepono/npm-internal-packages work and discussions with other researchers, he tested a hypothesis about companies whose internal package names he could enumerate — from public JS bundles, GitHub slip-ups, and LinkedIn-referenced repositories. He registered matching names on public npm/PyPI/RubyGems registries, pushed a version like 99.0.0, and added a trivial post-install script that phoned home with the hostname and path. No exploits, no data theft — just proof of execution. Over weeks, callbacks arrived from build machines and developer laptops inside Apple, Microsoft, PayPal, Shopify, Netflix, Yelp, Tesla and dozens more. Each paid a bounty; his Medium post, “Dependency Confusion: How I Hacked Into Apple, Microsoft and Dozens of Other Companies,” landed on 9 February 2021 and detonated across the industry.

Within days, the technique was industrialised. In mid-February 2021, attackers targeting two fintech firms (among them reported cases at Snyk-disclosed customers) pushed packages whose install scripts not only phoned home but dropped ransom notes demanding payment to prevent “further action.” Fiji and other researchers documented hundreds of copycat registrations hunting for internal-name collisions across ecosystems. Registries responded with namespace-protection policies — notably, GitHub/npm tightened rules around typosquat-adjacent registrations, and PyPI increased publisher verification options — but the underlying resolver behaviour remained: it is a design property, not a bug to patch away.

The episode also crowned a recognition that SSRF-style logic flaws in build infrastructure are a top-tier risk class. It sits on the timeline between SUNBURST (six weeks earlier) and Log4Shell (ten months later) as the middle chapter of the modern supply-chain era: SUNBURST showed vendors can be compromised; dependency confusion showed the assembly itself can be attacker-controlled without touching anyone’s network.

How it worked

The trick lives in resolver precedence. Most enterprises configure a private registry (Artifactory, Nexus, GitHub Packages) as a mirror/proxy that fronts public registries. Resolution order and version selection, however, still favour the highest semver match across sources. An internal-only name never reserved publicly is therefore claimable by anyone.

company build requests package "zorg-utils" v1.2.0 (internal)
   private registry proxies: check internal - found
   ALSO checks public registries (default proxy behaviour)
        |
attacker pre-registered "zorg-utils" v99.0.0 on npm/PyPI
   semver: 99.0.0 > 1.2.0 -> public package WINS resolution
        |
post-install script executes on build/CI runner
   -> attacker code runs inside corp network
   -> exfil hostname, paths, env vars (or ransom note)

Two details make it durable knowledge. First, internal names are embarrassingly enumerable: JavaScript bundles shipped to browsers, public repos with typos, and job posts reveal them; Birsan needed no insider access for any of the 35+ hits. Second, the primitive is ecosystem-agnostic — npm, PyPI, RubyGems, and (with variations) Go modules and Docker tags all had analogous behaviours, which is why “name your internal packages under a reserved scope” became universal guidance.

data-hmmnm-seam="2">

Impact and numbers

Metric Value Source
Organisations compromised in original research 35+ (Apple, Microsoft, PayPal, Tesla, Shopify…) Birsan Medium writeup, 2021-02-09
Bounties collected >$130,000 aggregate Birsan disclosures
Copycat extortion cases within 2 weeks (fintech-targeting packages with ransom notes) Snyk/Daniel Lessellovich reporting
Ecosystems affected npm, PyPI, RubyGems (concept generalises) writeup + follow-on research
Payload executed post-install script (hostname/path/env exfil) Birsan telemetry screenshots
data-hmmnm-seam="3">

Timeline

Date Event
2020-11 Related npm internal-packages research (awepono) sets the stage
2021-02-09 Birsan publishes dependency-confusion writeup; industry-wide review begins
2021-02 (mid) Copycat packages with ransom notes target fintechs
2021-02–03 Registry policy tightening; enterprises audit resolver configs
2021 onward Technique joins the standing supply-chain playbook (typosquats, protestware, hijacks)
data-hmmnm-seam="4">

Why it still matters in 2026

Dependency confusion remains the supply-chain attack that requires zero vulnerabilities — only naming discipline, which makes it the cheapest attack to prevent and the most embarrassing to fall to. Every registry-namespace policy, provenance-verification option, and SBOM initiative since 2021 traces partly to February 2021. The modern defensive stack — scoped internal names, resolver allow-lists, lockfile enforcement, install-hook restrictions — is now standard guidance in our software supply chain security guide, and the attack’s descendants (from protestware payloads to AI-model registry confusion) keep proving the class survives each new ecosystem.

data-hmmnm-seam="5">

Detection and hardening takeaways

  • Namespace your internal packages. Reserve your org scope on public registries (e.g., @company/) and use it for anything internal, even if never published.
  • Lock resolution to declared sources. Configure private registries in proxy-only mode for approved public scopes; internal names must never resolve publicly.
  • Enforce lockfiles hash-pinned in CI. Verify package-lock.json/Pipfile.lock integrity in CI; flag any resolution that differs from the lock as a supply-chain event, not a warning.
  • Restrict install hooks. Run installs with lifecycle-scripts disabled by default; allow-list the few packages that legitimately need them.
  • Alert on first-seen internal names going public. Monitor registry for your org’s internal package names appearing publicly — treat as a supply-chain incident, not a curiosity.

FAQ

Is dependency confusion still possible in 2026?

Yes, wherever resolver configuration is sloppy — which periodic bug-bounty reports and copycat registrations keep confirming. The mitigations are well known and cheap, which is precisely why falling to it in 2026 reads as negligence rather than misfortune.

How is this different from typosquatting?

Typosquatting waits for a human to mistype a name; dependency confusion needs no mistake — the build system itself selects the attacker’s package because version arithmetic prefers it. The attacker also does not guess: internal names leak from bundles and repos, so targeting is precise.

What did the original research actually execute on victim machines?

A post-install script that collected the machine hostname, working directory, and installation path and sent them to Birsan’s collection endpoint — deliberately non-invasive proof-of-execution. The copycats demonstrated what the same primitive looks like with criminal intent: identical mechanism, ransom note instead of ping.

data-hmmnm-seam="end">

Prabhu Kalyan Samal

Application Security Consultant at TCS. Certifications: CompTIA SecurityX, Burp Suite Certified Practitioner, Azure Security Engineer, Azure AI Engineer, Certified Red Team Operator, eWPTX v3, LPT, CompTIA PenTest+, Professional Cloud Security Engineer, SC-900, SC-200, PSPO I, CEH, Oracle Java SE 8, ISP, Six Sigma Green Belt, DELF, AutoCAD. Writing about ethical hacking, security tutorials, and tech education at Hmmnm.