Advisories for Pypi/Vyper package

2024

vyper performs incorrect topic logging in raw_log

Incorrect values can be logged when raw_log builtin is called with memory or storage arguments to be used as topics. A contract search was performed and no vulnerable contracts were found in production. In particular, no uses of raw_log() were found at all in production; it is apparently not a well-known function.

vyper performs double eval of the slice args when buffer from adhoc locations

Using the slice builtin can result in a double eval vulnerability when the buffer argument is either msg.data, self.code or <address>.code and either the start or length arguments have side-effects. A contract search was performed and no vulnerable contracts were found in production. Having side-effects in the start and length patterns is also an unusual pattern which is not that likely to show up in user code. It is also …

vyper performs double eval of raw_args in create_from_blueprint

Using the create_from_blueprint builtin can result in a double eval vulnerability when raw_args=True and the args argument has side-effects. A contract search was performed and no vulnerable contracts were found in production. In particular, the raw_args variant of create_from_blueprint was not found to be used in production.

vyper default functions don't respect nonreentrancy keys

Prior to v0.3.0, default() functions did not respect the @nonreentrancy decorator and the lock was not emitted. This is a known bug and was already visible in the issue tracker (https://github.com/vyperlang/vyper/issues/2455), but it is being re-issued as an advisory so that tools relying on the advisory publication list can incorporate it into their searches. A contract search was additionally performed and no vulnerable contracts were found in production.

Vyper's `_abi_decode` vulnerable to Memory Overflow

Summary If an excessively large value is specified as the starting index for an array in _abi_decode, it can cause the read position to overflow. This results in the decoding of values outside the intended array bounds, potentially leading to bugs in contracts that use arrays within _abi_decode. The advisory has been assigned low severity, because it is only observable if there is a memory write between two invocations of …

Improper Validation of Array Index

Vyper is a Pythonic Smart Contract Language for the Ethereum Virtual Machine. Arrays can be keyed by a signed integer, while they are defined for unsigned integers only. The typechecker does not throw when spotting the usage of an int as an index for an array. The typechecker allows the usage of signed integers to be used as indexes to arrays. The vulnerability is present in different forms in all …

Use of a Broken or Risky Cryptographic Algorithm

Vyper is a Pythonic Smart Contract Language for the EVM. There is an error in the stack management when compiling the IR for sha3_64. Concretely, the height variable is miscalculated. The vulnerability can't be triggered without writing the IR by hand (that is, it cannot be triggered from regular vyper code). sha3_64 is used for retrieval in mappings. No flow that would cache the key was found so the issue …

Improper Restriction of Operations within the Bounds of a Memory Buffer

Vyper is a Pythonic Smart Contract Language for the Ethereum Virtual Machine. When calls to external contracts are made, we write the input buffer starting at byte 28, and allocate the return buffer to start at byte 0 (overlapping with the input buffer). When checking RETURNDATASIZE for dynamic types, the size is compared only to the minimum allowed size for that type, and not to the returned value's length. As …

Improper Restriction of Operations within the Bounds of a Memory Buffer

Vyper is a pythonic Smart Contract Language for the ethereum virtual machine. In versions 0.3.10 and earlier, the bounds check for slices does not account for the ability for start + length to overflow when the values aren't literals. If a slice() function uses a non-literal argument for the start or length variable, this creates the ability for an attacker to overflow the bounds check. This issue can be used …

Improper Check for Unusual or Exceptional Conditions

Vyper is a pythonic Smart Contract Language for the ethereum virtual machine. Vyper compiler allows passing a value in builtin raw_call 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 …

concat built-in can corrupt memory in vyper

concat built-in can write over the bounds of the memory buffer that was allocated for it and thus overwrite existing valid data. The root cause is that the build_IR for concat doesn't properly adhere to the API of copy functions (for >=0.3.2 the copy_bytes function). A contract search was performed and no vulnerable contracts were found in production. Tracked in issue https://github.com/vyperlang/vyper/issues/3737

2023

Incorrect Calculation

Vyper is a Pythonic Smart Contract Language for the Ethereum Virtual Machine (EVM). Contracts containing large arrays might underallocate the number of slots they need by 1. Prior to v0.3.8, the calculation to determine how many slots a storage variable needed used math.ceil(type_.size_in_bytes / 32). The intermediate floating point step can produce a rounding error if there are enough bits set in the IEEE-754 mantissa. Roughly speaking, if type_.size_in_bytes is …

Vyper's `_abi_decode` input not validated in complex expressions

Impact _abi_decode() does not validate input when it is nested in an expression. the following example gets correctly validated (bounds checked): x: int128 = _abi_decode(slice(msg.data, 4, 32), int128) however, the following example is not bounds checked @external def abi_decode(x: uint256) -> uint256: a: uint256 = convert(_abi_decode(slice(msg.data, 4, 32), (uint8)), uint256) + 1 return a # abi_decode(256) returns: 257 the issue can be triggered by constructing an example where the output …

Out-of-bounds Write

Vyper is a Pythonic Smart Contract Language for the Ethereum Virtual Machine (EVM). In version 0.3.9 and prior, under certain conditions, the memory used by the builtins raw_call, create_from_blueprint and create_copy_of can be corrupted. For raw_call, the argument buffer of the call can be corrupted, leading to incorrect calldata in the sub-context. For create_from_blueprint and create_copy_of, the buffer for the to-be-deployed bytecode can be corrupted, leading to deploying incorrect bytecode. …

Deadlock

Vyper is a Pythonic Smart Contract Language for the Ethereum Virtual Machine (EVM). Starting in version 0.2.9 and prior to version 0.3.10, locks of the type @nonreentrant("") or @nonreentrant('') do not produce reentrancy checks at runtime. This issue is fixed in version 0.3.10. As a workaround, ensure the lock name is a non-empty string.

Always-Incorrect Control Flow Implementation

Vyper is a Pythonic Smart Contract Language. In affected versions the order of evaluation of the arguments of the builtin functions uint256_addmod, uint256_mulmod, ecadd and ecmul does not follow source order. This behaviour is problematic when the evaluation of one of the arguments produces side effects that other arguments depend on. A patch is currently being developed on pull request #3583. When using builtins from the list above, users should …

Always-Incorrect Control Flow Implementation

Vyper is a Pythonic Smart Contract Language. For the following (probably non-exhaustive) list of expressions, the compiler evaluates the arguments from right to left instead of left to right. unsafe_add, unsafe_sub, unsafe_mul, unsafe_div, pow_mod256, |, &, ^ (bitwise operators), bitwise_or (deprecated), bitwise_and (deprecated), bitwise_xor (deprecated), raw_call, <, >, <=, >=, ==, !=, in, not in (when lhs and rhs are enums). This behaviour becomes a problem when the evaluation of …

Vyper has incorrectly allocated named re-entrancy locks

In versions 0.2.15, 0.2.16 and 0.3.0, named re-entrancy locks are allocated incorrectly. Each function using a named re-entrancy lock gets a unique lock regardless of the key, allowing cross-function re-entrancy in contracts compiled with the susceptible versions. A specific set of conditions is required to result in misbehavior of affected contracts, specifically: A .vy contract compiled with either of the following vyper versions: 0.2.15, 0.2.16, 0.3.0 A primary function that …

Unchecked Return Value

Vyper is a Pythonic programming language that targets the Ethereum Virtual Machine (EVM). Prior to version 0.3.10, the ecrecover precompile does not fill the output buffer if the signature does not verify. However, the ecrecover builtin will still return whatever is at memory location 0. This means that the if the compiler has been convinced to write to the 0 memory location with specially crafted data (generally, this can happen …

Always-Incorrect Control Flow Implementation

Vyper is a pythonic Smart Contract Language for the ethereum virtual machine. In contracts with more than one regular nonpayable function, it is possible to send funds to the default function, even if the default function is marked nonpayable. This applies to contracts compiled with vyper versions prior to 0.3.8. This issue was fixed by the removal of the global calldatasize check in commit 02339dfda. Users are advised to upgrade …

Out-of-bounds Write

Vyper is a Pythonic smart contract language for the Ethereum virtual machine. Prior to version 0.3.8, during codegen, the length word of a dynarray is written before the data, which can result in out-of-bounds array access in the case where the dynarray is on both the lhs and rhs of an assignment. The issue can cause data corruption across call frames. The expected behavior is to revert due to out-of-bounds …

Integer Overflow or Wraparound

Vyper is a Pythonic smart contract language for the Ethereum virtual machine. Prior to version 0.3.8, due to missing overflow check for loop variables, by assigning the iterator of a loop to a variable, it is possible to overflow the type of the latter. The issue seems to happen only in loops of type for i in range(a, a + N) as in loops of type for i in range(start, …

Function Call With Incorrect Order of Arguments

Vyper is a Pythonic smart contract language for the Ethereum virtual machine. Prior to version 0.3.8, internal calls with default arguments are compiled incorrectly. Depending on the number of arguments provided in the call, the defaults are added not right-to-left, but left-to-right. If the types are incompatible, typechecking is bypassed. The ability to pass kwargs to internal functions is an undocumented feature that is not well known about. The issue …

vyper vulnerable to storage allocator overflow

Impact The storage allocator does not guard against allocation overflows. This can result in vulnerabilities like the following: owner: public(address) take_up_some_space: public(uint256[10]) buffer: public(uint256[max_value(uint256)]) @external def initialize(): self.owner = msg.sender @external def foo(idx: uint256, data: uint256): self.buffer[idx] = data Per @toonvanhove, "An attacker can overwrite the owner variable by calling this contract with calldata: 0x04bc52f8 fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff (spaces inserted for readability) 0x04bc52f8 is the selector for foo(uint256, uint256), and the …

Always-Incorrect Control Flow Implementation

Vyper is a Pythonic Smart Contract Language for the ethereum virtual machine. In versions 0.3.1 through 0.3.7, the Vyper compiler generates the wrong bytecode. Any contract that uses the raw_call with revert_on_failure=False and max_outsize=0 receives the wrong response from raw_call. Depending on the memory garbage, the result can be either True or False. A patch is available and, as of time of publication, anticipated to be part of Vyper 0.3.8. …

2022

Multiple evaluation of contract address in call in vyper

Impact when a calling an external contract with no return value, the contract address could be evaluated twice. this is usually only an efficiency problem, but if evaluation of the contract address has side effects, it could result in double evaluation of the side effects. in the following example, Foo(msg.sender).bar() is the contract address for the following call (to .foo()), and could get evaluated twice interface Foo: def foo(): nonpayable …

Integer Overflow or Wraparound

Vyper is a pythonic Smart Contract Language for the ethereum virtual machine. In affected versions, the return of <iface>.returns_int128() is not validated to fall within the bounds of int128. This issue can result in a misinterpretation of the integer value and lead to incorrect behavior. As of v0.3.0, <iface>.returns_int128() is validated in simple expressions, but not complex expressions. Users are advised to upgrade. There is no known workaround for this …

Buffer Copy without Checking Size of Input ('Classic Buffer Overflow')

Vyper is a pythonic Smart Contract Language for the ethereum virtual machine. Versions of vyper prior to 0.3.2 suffer from a potential buffer overrun. Importing a function from a JSON interface which returns bytes generates bytecode which does not clamp bytes length, potentially resulting in a buffer overrun. Users are advised to upgrade. There are no known workarounds for this issue.

Incorrect Comparison

Vyper is a Pythonic Smart Contract Language for the Ethereum Virtual Machine. In version 0.3.1 and prior, bytestrings can have dirty bytes in them, resulting in the word-for-word comparisons giving incorrect results. Even without dirty nonzero bytes, two bytestrings can compare to equal if one ends with "\x00" because there is no comparison of the length. A patch is available and expected to be part of the 0.3.2 release. There …

2021

Storage corruption due to variables overwritten by re-entrancy locks

Background When attempting to use the v0.2.14 release, @pandadefi discovered an issue using the @nonreentrant decorator. Impact Reentrancy protection storage slots get allocated to the same slots as storage variables, leading to the corruption of storage variables when using the @nonreentrant decorator. Patches This issue was fixed in v0.2.15 in #2391, #2379 Workarounds Don't use the @nonreentrant decorator in these versions.

VVE-2021-0002: Incorrect `returndatasize` when using simple forwarder proxies deployed prior to EIP-1167 adoption

Background @tjayrush reported a data handling issue with certain Web3 libraries using Vyper-deploy forwarder proxy contracts using our Vyper's built-in create_forwarder_to function prior to our change to support EIP-1167 style forwarder proxies. Impact If you are an end user of a forwarder-style proxy deployed using Vyper's built-in create_forwarder_to function AND you have a function that returns bytes AND you do no return data sanitation on the value returned, you could …

2020

Vyper interfaces returning integer types less than 256 bits can be manipulated if uint256 is used

VVE-2020-0001 Earlier today, we received a responsible disclosure of a potential issue from @montyly (security researcher at @trailofbits) for Vyper users who make assumptions about what values certain interface types can return. Impact We determined the issue to be mild and unlikely to be exploited, with an easy workaround while the correct resolution is in process. The issue stems from a number of things, which we will detail here. (1) …