GHSA-vgf2-gvx8-xwc3: Vyper Does Not Check the Success of Certain Precompile Calls
SummaryWhen the Vyper Compiler uses the precompiles EcRecover (0x1) and Identity (0x4), the success flag of the call is not checked. As a consequence an attacker can provide a specific amount of gas to make these calls fail but let the overall execution continue. Then the execution result can be incorrect.Based on EVM's rules, after the failed precompile the remaining code has only 1/64 of the pre-call-gas left (as 63/64 were forwarded and spent). Hence, only fairly simple executions can follow the failed precompile calls. Therefore, we found no significantly impacted real-world contracts.The fix is tracked in https://github.com/vyperlang/vyper/pull/4451.DetailsThe relevant precompilesEcRecoverEcRecover is used in vyper's `ecrecover` built-in. As the precompile consumes 3000 gas, any execution after an out-of-gas EcRecover call has at most 47 gas left.IdentityThe Identity precompile is used in vyper to perform memory copy operations. As its cost is variable, a variable amount of gas might be left after a failed call. The bigger the copy operation, the more gas can be left. Hence, a failed call to Identity could theoretically be followed by successful storage changes or emitted events.Identity is no longer used when `evm-version` `cancun` is used (because `MCOPY` is used instead). In 0.4.0 `cancun` is default, in 0.3.10 `cancun` is an option, otherwise `cancun` is not available. As only pre-`cancun` versions are relevant, we don't have to consider transient storage operations succeeding a failed call to Identity.The other precompilesCalls to `Sha2`, `ecAdd`, and `ecMul` have success checks and have had them for a long time.The precompiles `modexp`, `ripe`, `blake`, `ecPairing`, and `Point Evaluation` have no builtins in vyper.PoCIn the following we provide concrete examples of incorrectly generated bytecode. These examples are not optimized, but rather Proof-of-Concepts. The list is also not exhaustive.`ecrecover` useAffected versions: 0.2.0 - 0.4.0For older compiler versions (<=0.3.9) it behaves similarly to this [older advisory](https://github.com/vyperlang/vyper/security/advisories/GHSA-f5x6-7qgp-jhf3). As no data is returned, the previous value of the memory word is returned to the user. Hence, any dirty bytes might be returned. Contracts with older compiler versions and `ecrecover` were checked.For new vyper versions, the output buffer is zeroed, so when the call fails zero is returned. This is an incorrect result, but developers should anyway check for 0 as a failure case. Hence, this is unlikely to result in issues. However, we did search for such cases.As mentioned above at most 47 gas is left after the failed call, hence a `return` is the most realistic scenario to be attacked.Vulnerable Code:Problematic Call:Identity to copy Dynamic ArraysAffected versions: 0.3.2 - 0.3.9Dynamic Arrays might be copied on different occasionsThat copy operation can fail leading to incorrect accesses afterwardsVulnerable Code:Problematic Call:Identity in ABI Encoding of ReturndataAffected versions: 0.3.2 - 0.4.0Complex types such as Dynamic array with Strings inside need to be abi encoded before being returnedIn that `return` there is a memory copy which can failVulnerable Code:Problematic Call:Assertion based on data copied through IdentityAffected versions: 0.2.0 - 0.4.0An incomplete copy operation might falsify the result of a subsequent `assert`Vulnerable Code:Problematic Call:Identity used in `raw_revert`Affected versions: 0.3.8 - 0.4.0A copy operation might appear as part of raw_revertAs a result the revert reason might be incorrectVulnerable Code:Problematic Call:Identity to copy static arraysAffected versions: 0.2.0 - 0.4.0Vyper might perform a memory copy for static arrays, e.g. when moving them in and out of internal functionsAs this access is especially cheap (due to the static checks) it can also happen for smaller sizesVulnerable Code:Problematic Call:Identity to copy and return String or BytesAffected versions: 0.20 - 0.4.0Multiple situations in vyper might trigger a memory copy operation, e.g. moving data in and out of internal functionsIf the target buffer is later returned, incorrect data might be returnedVulnerable Code:Problematic Call:Identity and accessing the length of the target dataAffected versions: 0.3.10 - 0.4.0Accessing the data is fairly cheap, making it possible for smaller data copiesVulnerable Code:Problematic Call:Identity to copy and return String or BytesAffected versions: 0.3.10 - 0.4.0Multiple situations in vyper might trigger a memory copy operation, e.g. moving data in and out of internal functionsIf the target buffer is later returned, incorrect data might be returnedVulnerable Code:Problematic Call:ImpactA contract search was conducted and yielded no significant results.The advisory was rated a medium because the likelihood is low, but difficult to detect by source code analysis alone, and could yield unexpected results if a contract is affected by the bug.
CVSS v4.0: 2.3