Skip to content

Vyper negative array index bounds checks

Critical severity GitHub Reviewed Published Feb 7, 2024 in vyperlang/vyper • Updated Jun 20, 2024

Package

pip vyper (pip)

Affected versions

< 0.4.0

Patched versions

0.4.0

Description

Summary

Arrays can be keyed by a signed integer, while they are defined for unsigned integers only. The typechecker doesn't throw when spotting the usage of an int as an index for an array. Typically, negative integers are filtered out at runtime by the bounds checker, but small enough (i.e. large in magnitude, ex. -2**255 + 5) quantities combined with large enough arrays (at least 2**255 in length) can pass the bounds checker, resulting in unexpected behavior.

A contract search was performed, and no production contracts were found to be impacted.

Details

The typechecker allows the usage of signed integers to be used as indexes to arrays. The vulnerability is present in different forms in all versions. Here is an example from 0.3.10:
https://github.com/vyperlang/vyper/blob/c150fc49ee9375a930d177044559b83cb95f7963/vyper/semantics/types/subscriptable.py#L127-L137

As can be seen, the validation is performed against IntegerT.any().

PoC

If the array is sufficiently large, it can be indexed with a negative value:

arr: public(uint256[MAX_UINT256])

@external
def set(idx: int256, num: uint256):
    self.arr[idx] = num

For signed integers, the 2's complement representation is used. Because the array was declared very large, the bounds checking will pass (negative values will simply be represented as very large numbers):
https://github.com/vyperlang/vyper/blob/a1fd228cb9936c3e4bbca6f3ee3fb4426ef45490/vyper/codegen/core.py#L534-L541

Patches

Patched in vyperlang/vyper#3817.

Impact

There are two potential vulnerability classes: unpredictable behavior and accessing inaccessible elements.

  1. If it is possible to index an array with a negative integer without reverting, this is most likely not anticipated by the developer and such accesses can cause unpredictable behavior for the contract.

  2. If a contract has an invariant in the form assert index < x where both index and x are signed integers, the developer might suppose that no elements on indexes y | y >= x are accessible. However, by using negative indexes this can be bypassed.

The contract search found no production contracts impacted by these two classes of issues.

References

@charles-cooper charles-cooper published to vyperlang/vyper Feb 7, 2024
Published by the National Vulnerability Database Feb 7, 2024
Published to the GitHub Advisory Database Feb 7, 2024
Reviewed Feb 7, 2024
Last updated Jun 20, 2024

Severity

Critical

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
High

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

EPSS score

0.068%
(31st percentile)

Weaknesses

CVE ID

CVE-2024-24563

GHSA ID

GHSA-52xq-j7v9-v4v2

Source code

Credits

Loading Checking history
See something to contribute? Suggest improvements for this vulnerability.