On December 14, 2023, the @ledgerhq/connect-kit npm package was compromised via a phished former employee's GitHub account. Malicious versions 1.1.5, 1.1.6, and 1.1.7 shipped a wallet drainer that executed in the browsers of users visiting any DeFi application integrating Ledger Connect Kit. Reported losses totaled around $610,000. The exposure window was short (roughly two hours between publication and takedown) but the downstream impact continued for days as CDN caches served stale versions.
This incident is one of the clearer examples of how Web3 frontend supply chain trust breaks. It is worth studying not for novelty but for the specificity of what went wrong.
How did the attacker get npm publish access?
A phishing email to a former Ledger employee captured GitHub credentials, which still had access to the npm publishing account.
Ledger confirmed the attacker sent a social-engineering email to a former employee. The employee entered credentials into a phishing page. Those credentials unlocked GitHub, and via an integrated npm publishing flow, they unlocked the ability to push new versions of @ledgerhq/connect-kit. The account had not been deprovisioned after the employee left, which is a common failure of offboarding hygiene.
The attacker pushed three consecutive versions, which is consistent with an attempt to ensure propagation through semver ranges. Any project depending on ^1.1.4 resolved to the poisoned versions on install or CDN fetch.
What did the payload do in the browser?
The payload loaded a wallet-drainer library that modified transactions at signing time.
When a user visited a DeFi site using Connect Kit and connected their hardware wallet, the compromised code ran in the page context. It altered the transaction parameters before the wallet prompted the user to sign. Users saw one transaction in the dapp UI, but the wallet was signing a different transaction that transferred funds to attacker-controlled addresses. This is known as a "blind signing" attack because hardware wallets like Ledger historically displayed limited transaction context, making it hard for users to detect the substitution.
The drainer targeted ERC-20 approvals specifically, which allows repeated draining after a single approval. Victims who approved a malicious approval could lose funds days later as the attacker called transferFrom.
Why did the attack reach production sites so fast?
Many DeFi sites loaded Connect Kit directly from CDN without pinning specific versions or using integrity hashes.
Ledger's documentation at the time recommended loading Connect Kit via a <script src="https://cdn.jsdelivr.net/npm/@ledgerhq/connect-kit-loader"> pattern. This resolves to the latest version automatically. When the malicious 1.1.5 was published, CDN edges started serving it within minutes. Popular DeFi interfaces including Sushi, Lido, Zapper, Revoke.cash, and Kyber Network were affected.
Even teams that bundled Connect Kit into their own frontend builds were exposed if their CI ran during the window, because any unpinned install would pick up the malicious version. A review of affected sites post-incident showed that very few had subresource integrity hashes on third-party scripts, and very few had version pinning.
How was the attack detected and contained?
A security researcher noticed anomalous transaction flow on a DeFi site, traced it to Connect Kit, and reported it publicly.
Within about two hours of malicious publication, a researcher published screenshots of the drainer payload on X. Ledger's security team confirmed, yanked the malicious versions from npm, invalidated the compromised credentials, and pushed a clean 1.1.8. WalletConnect (a related project) and major DeFi platforms began coordinated takedowns across their integrations.
The lag was not in response once detection happened; it was in detection itself. There was no automated alerting on the npm publish event, no behavioral diff on the package bundle, and no signal to downstream consumers that the package had changed unexpectedly. Detection relied on a single human reading a network trace.
What should Web3 frontends change?
Four things, ordered by impact.
First, pin every third-party script with explicit version numbers and SRI hashes. This is table stakes for any external dependency, and Web3 raises the cost of getting it wrong because drainers are weaponized fast. A <script integrity="sha384-..."> would have blocked the Ledger payload.
Second, host critical integration code yourself. For libraries like Connect Kit that are small and stable, pulling them into your own build pipeline and serving from your CDN shifts the trust boundary from "npm + jsDelivr" to "your own release process." This does not eliminate compromise risk, but it scopes it.
Third, use clear-signing wallets. The industry has shifted toward wallets that display full transaction details (EIP-712 structured data, ERC-20 approval amounts in plain text, destination addresses prominently shown). Ledger devices now support clear-signing for major protocols. For users, approving only on clear-signing-enabled flows reduces drainer effectiveness.
Fourth, rotate access on offboarding, aggressively. The single highest-leverage change Ledger could have made was removing the former employee's GitHub access when they left. Offboarding reviews that include all connected OAuth tokens, npm permissions, and CI secrets should be a checklist item, not an assumption.
For Web3 teams specifically, add transaction simulation as a user-facing safety net: before the user signs, simulate the transaction against a forked state and show the actual effect. This pattern catches drainers even when the underlying JS has been compromised.
What does offboarding look like when done properly?
Offboarding is not a single checkbox; it is a dependency graph traversal that mirrors onboarding.
When a person joins an engineering organization, they are granted access to a sprawling set of resources: GitHub organization membership, npm publisher rights on shared packages, cloud console access, deployment keys, CI secrets, chat channels, ticketing systems, design tools, production databases. Most of those grants happen gradually over months, often informally. When the person leaves, the reverse process is rarely as thorough. A GitHub org may be ticked off, but the npm publish rights that were attached to that GitHub identity may persist. A cloud IAM role may be revoked, but a long-lived API key issued to that role may still work.
The Ledger incident turned on exactly this gap: a former employee's GitHub account was still active enough to publish to npm. A disciplined offboarding process looks like: produce an automated inventory of every system the person had access to, revoke each, rotate any credentials that the person may have had visibility into, and verify that publishes, deploys, and commits attributed to that identity are now rejected. For maintainers of critical packages, add specific checks: can this person still push to npm, can they still merge to main, can they still sign releases. Run offboarding as a ticket with a checklist and a reviewer, not as an informal handoff.
The cost of doing this rigorously is a few hours of work per offboarding. The cost of not doing it is the incident cost, which in Ledger's case ran to six figures plus ecosystem-wide trust damage.
How Safeguard.sh Helps
Safeguard.sh's reachability analysis identifies third-party JavaScript with signing-authority exposure as maximum-priority supply chain risk, using the 60-80% noise reduction to surface it above lower-impact SCA findings. Griffin AI builds behavioral profiles for packages used in Web3 flows and flags new outbound fetches, DOM manipulation of wallet prompts, and transaction-shape changes before public disclosures land. The SBOM pipeline inventories frontend assets and CDN-loaded code at 100-level dependency depth, so teams can answer "which dapps load the compromised version from which CDN" immediately. TPRM flows gate Web3 suppliers, and container self-healing rolls back affected builds the moment an upstream integrity signal shifts.