Full Report
LayerZero is a very large blockchain bridge that holds a large amount of value, as well as many cross-chain applications made by other developers. The functionality for calling is fairly simple on the smart contract side. On the sending side, call send() to the UltraLightNode (ULN) contract which emits an event. On the other chain, receive() is called from an entrypoint of LZ after a Merkle proof is done. Trust includes a nice callstack for this as well. A user can pick a specific relayer while doing this. When getting a relayer to send over the message, you need to pay for gas as well. In September of 2022, ULNv1 was deprecated. Why? Trust claims it was a silent fix of a vulnerability with no public information about it. If you look at a diff of the codebases, instead of just srcAddress it's using srcAddress,dstAddress for the PacketReceived event. When calling validateTransactionProof() on a transaction the nonce used to be pulled from the mapping [srcChainId][srcAddress]. Now, it's [srcChainId][srcAddress][dstAddress]. Why is this a big deal? The incoming transactions must come in order as well... 1,2,3... A client contract can pick their own relayer/oracle pair. Given this information, we have a slot collision. Another user can submit a transaction from the same client contract with a different relayer to the same destination and chain to spoof it. Since there is replay protection, this made the real message unreceivable. Boom! $250K was paid to the first whitehat then samczsun reported it after but got a $50K good will bounty. To me, the slot collision is something I've never seen before and I'd be curious to see more of these. Thinking in depth about mapping and user controllable values seems like a good way to go.
Analysis Summary
# Vulnerability: LayerZero ULNv1 Message Path Slot Collision
## CVE Details
- **CVE ID**: N/A (Disclosed as a silent fix/deprecation by the vendor)
- **CVSS Score**: Estimated 7.5 (High)
- **CWE**: CWE-694 (Use of Multiple Proxies with Shared State) / Logical Slot Collision
## Affected Systems
- **Products**: LayerZero Protocol
- **Versions**: UltraLightNode v1 (ULNv1)
- **Configurations**: Applications using the default ordered messaging delivery where a client contract can select a custom Relayer/Oracle pair.
## Vulnerability Description
The vulnerability stems from an architectural flaw in how ULNv1 tracked message nonces. In ULNv1, the messaging library used a mapping indexed only by `[srcChainId][srcAddress]` to track the expected inbound nonce.
Because a user (or a malicious actor) could pick a specific Relayer/Oracle pair for a transaction, an attacker could submit a transaction from the same source client contract to the *same* destination chain but targeting a *different* destination address. Because the nonce mapping did not include the `dstAddress`, these separate message paths shared the same nonce slot. By successfully delivering a "spoofed" or irrelevant message first, the attacker increments the nonce, causing the legitimate message to have an "out-of-order" nonce. Because LayerZero enforces strict ordering (1, 2, 3...), the legitimate message becomes permanently unreceivable.
## Exploitation
- **Status**: PoC available (Reported by Whitehats; no known malicious exploitation in the wild prior to patch)
- **Complexity**: Medium
- **Attack Vector**: Network
## Impact
- **Confidentiality**: None
- **Integrity**: Low (Spoofed messages could be injected into the delivery pipeline)
- **Availability**: High (Permanent denial of service/griefing of cross-chain messages)
## Remediation
### Patches
- **ULNv2**: LayerZero deprecated ULNv1 in September 2022 and migrated to ULNv2. The new version updates the state mapping to use `[srcChainId][srcAddress][dstAddress]`, effectively isolating message paths.
### Workarounds
- **Library Upgrade**: Integrated applications were required to move to the UltraLightNodeV2 messaging library.
- **Contract Ownership**: For decentralized applications, the ability to update the ULN address is required to recover stuck funds; otherwise, the "blocking" of the channel is permanent.
## Detection
- **Indicators of Compromise**: Discrepancies between the expected `inboundNonce` on the destination chain and the nonce emitted by the source chain for a specific contract.
- **Detection Methods**: Analysis of mapping indices in smart contract logic to ensure all unique logical paths are represented in the key (e.g., ensuring `dstAddress` is part of the unique identifier for a delivery path).
## References
- LayerZero ULNv1 Deprecation Post: hxxps[://]medium[.]com/layerzero-official/ulnv1-deprecation-4c2ee94611cb
- Trust Security Case Study: hxxps[://]www[.]trust-security[.]xyz/post/learning-by-breaking-a-layerzero-case-study-part-one
- LayerZero GitHub: hxxps[://]github[.]com/LayerZero-Labs/LayerZero