Lessons on Supply Chain Security that Can Be Learned From the Vyper Exploit
Curve and other DeFi projects fell victim to an exploit due to a vulnerability in the Vyper reentrancy protection.
A lot will be written over the next few days about this particular case and the Vyper language, but the exploit highlights one particular issue that is often overlooked in DeFi development: supply chain security. DeFi protocols are critical software. Other sectors where software security is crucial, such as aeronautics, healthcare, and even traditional finance, treat dependencies as vital for security.
When we audit a set of smart contracts, often more than 70% of the codebase consists of third-party libraries. Add to this the compiler, the node implementation software, the testing framework, and the wallet used for deployment, and it becomes clear that only a small portion of the code actually depends on the development teams’ own security efforts. In our layer 1 audits, we see an even larger degree of dependencies.
What could DeFi do to confront these kinds of threats? Let’s review some well-known software development practices from other industries with critical software that could guide our SDLC (Software Development Life Cycle):
- Use only mature, well-tested, and established libraries. For example, we have often found experimental implementations of cryptographic primitives during layer 1 and wallet audits. It is essential to use libraries that were under the scrutiny of security researchers for a long time for critical components whenever possible. Of course, this might not always be possible, but consider adoption rate and test coverage as additional quality indicators.
- Effective version control with pinning can prevent unintentional introductions of unchecked dependencies, while, at the same time, keeping developers aware of critical fixes.
- Reduce dependencies to a minimum. This does not mean re-inventing the wheel, but simplicity of design and incremental feature implementation can help to keep the dependency tree manageable.
- Software Composition Analysis (SCA): SCA tools can be used to analyze the open source components of the software, detect vulnerabilities, and identify any components that are out-of-date or that don’t comply with the organization’s policies.
- Don’t use the latest of the latest. When Curve adopted Vyper, the language was mainly unaudited and in an early stage of maturity. It is usually best to treat new releases with caution. This is particularly true with paradigm-breaking software, such as a compiler for a new programming language, but also for major tooling and library version updates.
- Don’t rely solely on built-in protection mechanisms if secure patterns exist as an alternative. The Vyper exploit was possible due to a bug in the built-in reentrancy protections. We have often argued against reentrancy guards since simply not trusting any external calls and using corresponding design patterns is a simpler option.
- Strive for technological diversity. Ethereum deliberately encourages this by supporting node implementations in different languages. There are Go implementations, Rust implementations, and Java implementations. This means supply chains are made up of different compilers, different library dependencies, and even different programming paradigms. A critical node vulnerability is, thus, less likely to bring down the whole network. This is not the case in some other ecosystems, where an exploit in a single library could affect every single node.
Admittedly, there are limited choices for writing smart contracts in Ethereum at the time Curve made their choice, Solidity and Vyper. More modern alternatives, such as Fe are being developed, but they are still early in their development cycles. There is not too much a project can do to spread the risk at this level. However, the projects exploited did take a certain risk by adopting Vyper very early in its development cycle.
It is important to pause a bit and think about supply chain risks. In addition, regularly auditing the codebase for security vulnerabilities and conducting peer code reviews can help detect any potential issues early on. This includes checking for issues in the code as well as in any dependencies.