Authors: Scroll Security Council
Overview
On April 25, the Scroll Security Council performed an emergency upgrade to the Scroll mainnet, to address two bugs discovered in the OpenVM circuit and bridge contract:
-
A soundness issue in OpenVM 1.0.0 reported by Axiom.
This bug was present in OpenVM circuit, allowing a colluding sequencer and prover to generate invalid proofs while still being able to pass the onchain verifier.
-
A message queue spoofing issue reported on Immunefi.
This bug was introduced by recent changes in the enforced transaction gateway contract. If exploited, it could allow an attacker to mint ETH or arbitrary ERC20 tokens on Scroll.
Scroll took immediate action to pause the affected gateway contract and secure funds before anyone exploited the bugs. Scroll worked with Axiom, the Immunefi whitehat, and the Scroll Security Council to promptly review and fix these two bugs and deploy the patches in this emergency upgrade.
Summary of Vulnerabilities
Issue 1: OpenVM circuit soundness issue
Details: Axiom reported a soundness issue in their OpenVM v1.0.0 release. The bug was located in the auipc
opcode circuit (here). An enumerator was derived from the iterator that skipped the first element. This resulted in the highest pc limb being range checked to 8-bits instead of 6-bits, allowing malicious provers to fill in arbitrary values to the highest 2-bits of the pc
in the witness.
for (i, limb) in pc_limbs.iter().skip(1).enumerate() {
if i == pc_limbs.len() - 1 {
// Range check the most significant limb of pc to be in [0,
// 2^{PC_BITS-(RV32_REGISTER_NUM_LIMBS-1)*RV32_CELL_BITS})
...
Fix: The fix requires one line change in extensions/rv32im/circuit/src/auipc/core.rs
:
// pc_limbs[0] is already range checked through rd_data[0]
- for (i, limb) in pc_limbs.iter().skip(1).enumerate() {
+ for (i, limb) in pc_limbs.iter().enumerate().skip(1) {
if i == pc_limbs.len() - 1 {
Impact Assessment: The exact exploit scenario is unclear. But any circuit soundness bug has a potentially severe impact. Currently, this bug cannot be exploited by third parties because both the sequencer and the provers are operated by Scroll.
The fix audit report is attached in the Appendix.
Issue 2: Message spoofing in the bridge
Details: On April 22, we received a bug bounty report about a vulnerability involving EnforcedTxGateway
. This vulnerability was introduced in Euclid phase-2, and unfortunately not uncovered during the audit.
The exploit consists of a maliciously crafted withdraw message on L2, which, when relayed to L1 (to L1ScrollMessenger.relayMessageWithProof
), would call EnforcedTxGateway.sendTransaction
to enqueue an enforced transaction. msg.sender
of this inner call would be L1ScrollMessenger
. As a result, the corresponding L2 transaction would spoof L1ScrollMessenger
on L2 (have the same aliased sender address), and could bypass access controls on L2ScrollMessenger
. Prior to Euclid, EnforcedTxGateway
did not allow calls from smart contract accounts, so this was not an issue.
Fix: The fix requires a single line change in src/L1/L1ScrollMessenger.sol
:
// @note check more `_to` address to avoid attack in the future when we add more gateways.
- if (_to == messageQueueV1 || _to == messageQueueV2) {
+ if (_to == messageQueueV1 || _to == messageQueueV2 || _to == enforcedTxGateway) {
revert ErrorForbidToCallMessageQueue();
}
Impact Assessment: If exploited, this vulnerability would allow an attacker to essentially mint an arbitrary amount of ETH or any ERC20 tokens on L2.
Mitigation: Shortly after receiving the report, Scroll dev team paused EnforcedTxGateway
so there is no imminent risk. If exploited, the chain would stop finalizing because Scroll operates an off-chain safeguard component chain-monitor
that monitors every deposit and mint event between L1 and L2. If it detects any mismatch, the chain-monitor
will halt the onchain finalization.
Note: Due to the urgency of this vulnerability, we were unable to obtain a full external audit of the fix before the emergency upgrade. After the internal team, the whitehat, and the Scroll Security Council independently verified that the fix was effective, we conducted the emergency upgrade. Later, Trail of Bits has attested that the fix is effective (see Appendix for the attestation).
Timeline
- 17 April: Received circuit vulnerability notice from Axiom.
- 17-23 April: Scroll dev team developed and tested the patched OpenVM circuits (see the public patch) on a private shadowfork network.
- 22 April: Euclid upgrade is concluded.
- 22 April: Received contract vulnerability report on Immunefi.
- 22 April: Scroll executed an emergency pause on the enforced transaction gateway contract in this transaction, shortly after receiving and reviewing the bug report.
- 23 April: Scroll submitted contract fix in a private repo (later moved to the public repo). The whitehat confirmed that the fix was effective.
- 24-25 April: The Scroll Security Council verified the fix independently and signed emergency upgrade transaction.
- 25 April: Scroll executed upgrade in this transaction, and unpaused enforced transaction gateway in this transaction.
Retrospective
The OpenVM bug, while serious, could not be meaningfully exploited on Scroll because the sequencer and provers are not permissionless. As we move toward decentralizing these components, we plan to implement additional safeguards, such as a multi-proof system, to mitigate the risk of circuit and prover vulnerabilities.
On the smart contract side, our security approach has relied on a combination of internal tests, code reviews, and third-party audits. Following this incident, we are strengthening our security practices in several key areas:
- We engaged with Trail of Bits for a post-mortem research (see Appendix for the full report), and will continue working with them to conduct a holistic assessment of the bridge contracts and implement their recommended protections.
- We are adding more static analysis tools and fuzzing tests to detect potential vulnerabilities earlier in the development cycle. We are also exploring formal verification of the contracts to prove the correctness of critical components and bridge logic.
- We are improving our internal review processes and external audit workflows to ensure that critical issues are identified and resolved before deployment to production.
Acknowledgement
We thank Axiom for the finding and disclosure of the bug and their prompt fix.
We thank WhiteHatMage for finding this bug and reporting it on our Immunefi bug bounty.