###### tags: `blog posts`, `Public`, `Ariel` # Disclosure of recent vulnerabilities We have recently patched two severe bugs in Aztec 2.0. The first was found by an Aztec engineer and the second by community members. **1. Lack of range constraints for the `tree_index` variable** #### Description of bug: The index (i.e. position) of a note in the Aztec 2.0 tree was used in the computation of the note nullifier. The code assumed this to be a 32-bit integer, and so used only the last 32-bits of this element as the tree index. However, the field element representing this position was not actually constrained to be 32 bits. Therefore, the entire field element was used as an input for computing the nullifier. #### Consequences: An attacker could use this mistake to spend the same note multiple times in the following way: While constructing the proofs for these spends, use values for the tree index agreeing with the correct tree index of the note they wish to spend on its last 32 bits while having (arbitrary) different values on the other bits. Such values would all pass the membership check showing the input note exists, but produce a different nullifier each time. Since the only defense against double spend in a private system like Zcash or Aztec 2.0 is disallowing repeated nullifiers, these values would allow the attacker to spend the same input multiple times. #### Mitigation: We have implemented an immediate fix adding a range check of 32 bits of the tree index variable to the joinsplit circuit. Longer term, we are working on a "positive integer" wrapper of field elements which would make it much harder to overlook buggy code. The wrapper would force developers to range constrain variables when they are initially constructed, unless an "unsafe mode" is explicitly used. #### Acknowledgements: The bug was found by Aztec engineer Kevaundray Wedderburn. **2. Insufficient range checks while emulating non-native field operations** #### Description of the bug: The [Aztec non-native/emulated field operations](https://hackmd.io/@arielg/B13JoihA8) rely on the Chinese Remainder Theorem (CRT). The basic idea is to use the CRT to show an identity holds over the integers, which implies the identity holds also modulo any prime, including the prime order of the field we are emulating. The main identity the code works with has the form: $$a\cdot b = p\cdot q +r,$$ i.e. division with remainder of $a\cdot b$ by $p$ - where $\mathbb{F}_p$ is the field we are emulating. The circuit generated checks this identity mod the native field modulus $n$ and mod $2^t$. This implies using the CRT the identity holds modulo $M:=2^t\cdot n$. However, $q$ was only range constrained to be smaller than $2^t$ and in our setting $p>n$. This means the right hand side of the equation could have contained integers larger than $M$. In that case we would be unable to deduce from the fact that the identity holds mod $M$ that it also holds over the integers, and therefore mod $p$. #### Consequences: An attacker could prove incorrect equations hold mod $p$ when using the `BigField` class. As this code was only used for rollup proofs, and Aztec itself is the only rollup provider so far, we can be sure that nobody else could have exploited this bug, unless they submitted rollup proofs of their own in the so-called 'escape-hatch window'. However, we have checked that no proofs have ever been submitted by parties besides Aztec. We are therefore certain that no 3rd party has exploited this bug (though it requires trusting that the Aztec team itself has not done so). #### Mitigation: We have added more strict range checks and asserts in the `BigField` class ensuring no one can create values as large as $M$ during the computations. #### Acknowledgements: The bug was discovered by community members Xin Gao and Onur Kilic. They will jointly receive a bounty of $50,000 USD. ### Retrospective We deeply appreciate the community's efforts to attack Aztec's codebase and algorithms to discover subtle bugs. Our community's efforts affirm the benefit of open source code and bug bounty programs as effective security measures in complex cryptographic systems. The above discoveries also demonstrate the well-known security benefits of independent implementations - Onur and Xi discovered the bug while working on an independent implementation by the Ethereum Foundation and Scroll Tech of emulated field operations, and Kev discovered the first bug while reimplementing Aztec 2.0 joinsplit circuit in Noir - our DSL for writing Plonk circuits. We thank Onur and Xi for their efforts and look forward to further collaboration with the broader cryptographic community.