vyperlang/vyper · Security

AugAssign evaluation order causing OOB write within the object in Vyper

GHSA ID
GHSA-4w26-8p97-f4jp
CVE ID
CVE-2025-27105
Severity
low
Published
Updated
CVSS v4
2.3 · CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N

Description

Vyper handles AugAssign statements by first caching the target location to avoid double evaluation. However, in the case when target is an access to a DynArray and the rhs modifies the array, the cached target will evaluate first, and the bounds check will not be re-evaluated during the write portion of the statement. In other words, the following code

def poc():
    a: DynArray[uint256, 2] = [1, 2]
    a[1] += a.pop()

is equivalent to:

def poc():
    a: DynArray[uint256, 2] = [1, 2]
    a[1] += a[len(a) - 1]
    a.pop()

rather than:

def poc():
    a: DynArray[uint256, 2] = [1, 2]
    s: uint256 = a[1]
    t: uint256 = a.pop()
    a[1] = s + t  # reverts due to oob access

CWEs

References