CVE-2024-24567: raw_call `value=` kwargs not disabled for static and delegate calls
Summary Vyper compiler allows passing a value in builtin rawcall even if the call is a delegatecall or a staticcall. But in the context of delegatecall and staticcall the handling of value is not possible due to the semantics of the respective opcodes, and vyper will silently ignore the value= argument.
A contract search was performed and no vulnerable contracts were found in production.
Details The IR for rawcall is built in the RawCall class: https://github.com/vyperlang/vyper/blob/9136169468f317a53b4e7448389aa315f90b95ba/vyper/builtins/functions.py#L1100
However, the compiler doesn't validate that if either delegatecall or staticall are provided as kwargs, that value wasn't set. For example, the following compiles without errors: python rawcall(self, calldata2, maxoutsize=255, isdelegatecall=True, value=msg.value/2)
Impact If the semantics of the EVM are unknown to the developer, he could suspect that by specifying the value kwarg, exactly the given amount will be sent along to the target. However in fact, no value will be sent.
Here is an example of an potentially problematic implementation of multicall utilizing the rawcall built-in: python valueaccumulator: uint256 = empty(uint256) results: DynArray[Result, maxvalue(uint8)] = [] returndata: Bytes[maxvalue(uint8)] = b"" success: bool = empty(bool) for batch in data: msgvalue: uint256 = batch.value valueaccumulator = unsafeadd(valueaccumulator, msgvalue) if (batch.allowfailure == False): returndata = rawcall(self, batch.calldata, maxoutsize=255, value=msgvalue, isdelegatecall=True) success = True results.append(Result({success: success, returndata: returndata})) else: success, returndata = \ rawcall(self, batch.calldata, maxoutsize=255, value=msgvalue, isdelegatecall=True, revertonfailure=False) results.append(Result({success: success, returndata: returndata})) assert msg.value == valueaccumulator, "Multicall: value mismatch" return results
Patches Fixed in https://github.com/vyperlang/vyper/pull/3755 Workarounds Is there a way for users to fix or remediate the vulnerability without upgrading?
References Are there any links users can visit to find out more?
Other sources
Vyper is a pythonic Smart Contract Language for the ethereum virtual machine. Vyper compiler allows passing a value in builtin rawcall even if the call is a delegatecall or a staticcall. But in the context of delegatecall and staticcall the handling of value is not possible due to the semantics of the respective opcodes, and vyper will silently ignore the value= argument. If the semantics of the EVM are unknown to the developer, he could suspect that by specifying the value kwarg, exactly the given amount will be sent along to the target. This vulnerability affects 0.3.10 and earlier versions.
— NVD
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pip/vyperto a version that resolves this vulnerability.Fixed in 0.4.0 - Upgrade
Upgrade
vyperto a version that resolves this vulnerability.Fixed in 0.3.10
Event History
Frequently Asked Questions
What is the severity of CVE-2024-24567?
CVE-2024-24567 is classified as a medium severity vulnerability due to its potential impact on smart contract execution.
How do I fix CVE-2024-24567?
To resolve CVE-2024-24567, update Vyper to version 0.4.0 or later.
What version of Vyper is affected by CVE-2024-24567?
CVE-2024-24567 affects Vyper versions prior to 0.4.0, including all versions up to 0.3.10.
What is the nature of the vulnerability in CVE-2024-24567?
CVE-2024-24567 allows a value to be passed to `raw_call` during `delegatecall` or `staticcall`, which is not allowed by the semantics of these opcodes.
Where can I find more information about CVE-2024-24567?
More details about CVE-2024-24567 can be found in the Vyper GitHub repository and security advisories.