LavaMoat and the Ledger Software Supply Chain Attack
Learn how LavaMoat offers triple-point protection in the software development cycle and how you can defend your app from an attack today.
What happened?
On December 14th, one of Ledger’s software libraries, Ledger Connect Kit, was the subject of a software supply chain attack.
The compromise allegedly originated when an ex-employee, who still had publishing access, fell victim to a phishing attack. This attack compromised their npm credentials. npm, or Node Package Manager, is a tool for importing open-source software libraries, broadly used across the web development industry, as well as web3.
This attack allowed a malicious version of the library in question to be published. This library is included in a live-updating manner via a Content Delivery Network (CDN) in many web apps in the Ethereum ecosystem. This resulted in malicious code being injected into those web apps.
How do we prevent this? LavaMoat.
LavaMoat is a set of tools built specifically to help address the software supply chain security issues web application developers face.
LavaMoat offers protections against supply chain attacks at three different points in the software development lifecycle: at the time of dependency install (when you’re importing all those libraries), at build time (when the app is being prepared for serving over the Internet), and at runtime (when the built application is running).
LavaMoat is unique in its runtime protections. There are other tools that can be used during development, such as snyk.io, which only provides warnings of known vulnerabilities, or socket.dev, which provides more comprehensive code analysis, and does not wait for experts to report findings to a central database. These scanning tools perform an invaluable role, and we recommend you use socket.dev’s GitHub Integration.
However, they are unable to provide any runtime guarantees. For this reason, we find using them alone to be insufficient.
LavaMoat’s security protections derive from only delegating specified capabilities to dependencies of your application.
What does that mean? Well, read on, and check out our Devcon 6 talk for a deeper understanding of how LavaMoat works and how it is used.
An Object Capability primer
You can think of a system having capabilities: things it can do, like showing information, reading locally stored data, or making requests to other systems like web requests to servers or transaction requests to wallets, and the ability to delegate these capabilities to others.
When delegating a capability, you can provide a limited or restricted version of the capability. This is known as attenuation.
These three components form the basis of the object capability security model. By using this model, you can understand who has the ability to do what.
Web application security
Browsers do a decent job of sandboxing applications; that is, keeping them separate and preventing them from interfering with your computer or other websites.
However, they don't provide robust building blocks for web app developers to further sandbox specific portions of their app, which could keep certain components of their app from compromising the whole application.
For this reason, when importing a library into your application, you are effectively delegating all capabilities to that library. This is further complicated by the fact that most JavaScript libraries bring in not just their own code but a collection of libraries written by various authors.
Ledger attack specifics
The @ledger/connect-kit-loader
library is Ledger’s recommended way of integrating with their products. This package is a thin wrapper that loads the latest version of their library from a CDN.
While this means your app will always have the latest version of the library it also means __you are effectively delegating control of your web app to the Ledger loader library, which in turn delegates it to the code hosted on the CDN. __
You can model the delegation chain like this:
Web App → @ledger/connect-kit-loader
→ jsDelivr CDN → npm → Ledger → Ledger ex-employee → attacker
Even this is a simplification. Zooming in on one component, such as the jsDeliver CDN, can reveal a dazzling complexity of additional services that are also part of the supplychain and potential footholds for launching an attack.
Securing applications with Object Capability Security
While browsers themselves don't provide much tooling, as mentioned, for limiting the capabilities of subcomponents of an application, the JavaScript language is actually well suited for the task.
JavaScript, with some careful effort, allows you to build Compartments, which limit what code is allowed to access. See Agoric’s Hardened Javascript effort for an implementation of Compartments.
MetaMask’s LavaMoat supply chain security system and the MetaMask Snaps plugin system both build on Compartments to achieve confinement.
Would LavaMoat have prevented the Ledger supplychain attack?
Asking if LavaMoat would have prevented it is kinda like asking if the stop-when-touched feature on a table saw would help if you held on to the saw while jumping off a cliff - yes, your fingers would likely remain attached to your hand after the jump.
In principle, the way @ledgerhq/connect-kit-loader
works forces the app developer to forgo many of established security best practices. But not all hope is lost.
The best way to let LavaMoat (and other supply-chain security tools) help you would be to use the @ledgerhq/connect-kit directly
, without handing all control off to the loader.
LavaMoat was designed to mitigate attacks like the Copay wallet hack, also known as “the event-stream incident”, and protects well against it. So, how does LavaMoat fare against this different attack?
The answer is, unfortunately, the age old “it depends”. LavaMoat is a tool for application developers, not library developers, due to the way it integrates in the app runtime. This means that while some webapps could have protected themselves with LavaMoat, applications without LavaMoat would still be vulnerable.
Additionally, LavaMoat only enforces a policy specified by the developers. If you specify an unsafe policy, LavaMoat will not be able to protect you.
Let's look at how an application with LavaMoat could have been protected from this attack.
LavaMoat uses a policy file to determine what capabilities, in the form of global platform APIs, a dependency should get. To make this easier, you can have LavaMoat analyze a package and automatically determine what a package seems to need in order to operate. This is known as static analysis.
While static analysis is an imperfect means of understanding what some code is trying to do, LavaMoat only uses static analysis for convenience to help you generate a policy file. It does not use static analysis to enforce its policies at runtime. The generated policies are then reviewed, tweaked, and approved by the developer.
For the original question, one answer is: Yes, LavaMoat can protect your app and your users from supply chain attacks, by preventing packages from having the capability to load new code at runtime. It can protect you if you have configured it correctly and if you used dependencies that don’t demand overly powerful capabilities.
Another answer is: No. If you had configured LavaMoat to allow @ledgerhq/connect-kit-loader
to operate normally and inject a script tag running any code it likes outside of the LavaMoat runtime, the attack still would have succeeded. This is part of LavaMoat’s compromise between backwards compatibility and a safer system. LavaMoat is very flexible in order to be maximally compatible, so you can drop it in your app without rewriting it from scratch. The responsibility is still on the app developer to set sensible policies and choose sensible dependencies. LavaMoat allows you to selectively provide global browser APIs, but some global APIs simply contain too much power to safely give to a third party package. We’re researching a few different means of further limiting these powers, but making something that just works for packages that make no effort to limit their control is challenging.
One of LavaMoat’s features, called Scuttling, would interfere with both the malicious and the original package as loaded by the @ledgerhq/connect-kit-loader
. Scuttling removes access to capabilities for code running outside the LavaMoat sandbox. This would prevent you from using the unsafe @ledgerhq/connect-kit-loader
to begin with, and push you towards directly using and thus owning the process of updating @ledgerhq/connect-kit
, ensuring you maintain full control of the code run in your app.
While LavaMoat is not a silver bullet, it gives you control and visibility where you would otherwise have none. LavaMoat should be just one tool in your security strategy.
Here’s what you can do right now to defend against an attack tomorrow:
- Add the free Socket.dev dependency monitor (2 min).
- Add a CSP with tight control of resources (30 min).
- Add LavaMoat to your build system and to your app bundle (1 hr).
Keep reading our latest stories
Developers, security news, and more