GHSA-2p94-8669-xg86 CVE-2025-26622 PYSEC-2025-29
Vyper's sqrt doesn't define rounding behavior
- Severity
- 0.0 / 10
- High · CVSS 4.0
- Exploit chance (EPSS)
- 0.33%
- Chance of exploitation in the next 30 days. Higher than 25.80% of scored vulnerabilities.
- Known exploited
- No
- Not in CISA's catalog
- Weakness
- CWE-682 Incorrect Calculation
- Fix
0.4.1- Upgrade vyper to this version or later
Description
Vyper's sqrt() builtin uses the babylonian method to calculate square roots of decimals. Unfortunately, improper handling of the oscillating final states may lead to sqrt incorrectly returning rounded up results.
the fix is tracked in https://github.com/vyperlang/vyper/pull/4486
Vulnerability Details
Vyper injects the following code to handle calculation of decimal sqrt. x is the input provided by user.
assert x >= 0.0
z: decimal = 0.0
if x == 0.0:
z = 0.0
else:
z = x / 2.0 + 0.5
y: decimal = x
for i: uint256 in range(256):
if z == y:
break
y = z
z = (x / z + z) / 2.0
Notably, the terminal condition of the algorithm is either z_cur == z_prev, or the algorithm runs for 256 rounds.
However, for certain inputs, z might actually oscillate between N and N + epsilon, where N ** 2 <= x < (N + epsilon) ** 2. This means that the current behavior does not define whether it will round up or down to the nearest epsilon.
The example snippet here returns 0.9999999999, the rounded up result for sqrt(0.9999999998). This is due to the oscillation ending in N + epsilon instead of N.
@external
def test():
d: decimal = 0.9999999998
r: decimal = sqrt(d) #this will be 0.9999999999
Note that sqrt() diverges from isqrt() here -- isqrt() consistently rounds down, so it is not subject to the same issue.
Impact Details
Since sqrt() can be used for determining boundary conditions, rounding down is preferred. However, since sqrt() is used very rarely in the wild, this advisory has been assigned an impact of low.
Affected versions
PyPI
| Package | Vulnerable | Fixed in |
|---|---|---|
| vyper | < 0.4.1 |
0.4.1 |
How to fix
Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.
vyper PyPI → 0.4.1
- pip
pip install --upgrade "vyper>=0.4.1"- poetry
poetry add "vyper>=0.4.1"- uv
uv add "vyper>=0.4.1"
Severity breakdown
CVSS 4.0 0.0
CVSS:4.0/AV:N/AC:H/AT:P/PR:L/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N
- Attack vector
- Network
- Attack complexity
- High
- Attack requirements
- Present
- Privileges required
- Low
- User interaction
- None
- Confidentiality (vulnerable system)
- Low
- Integrity (vulnerable system)
- Low
- Availability (vulnerable system)
- None
- Confidentiality (subsequent systems)
- None
- Integrity (subsequent systems)
- None
- Availability (subsequent systems)
- None
CVSS 3.1 7.5
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N
- Attack vector
- Network
- Attack complexity
- Low
- Privileges required
- None
- User interaction
- None
- Scope
- Unchanged
- Confidentiality
- None
- Integrity
- High
- Availability
- None
Weakness
CWE-682: Incorrect Calculation
The product performs a calculation that generates incorrect or unintended results that are later used in security-critical decisions or resource management.
How to prevent it
- Implementation: Understand your programming language's underlying representation and how it interacts with numeric calculation. Pay close attention to byte size discrepancies, precision, signed/unsigned distinctions, truncation, conversion and casting between types, "not-a-number" calculations, and how your language handles numbers that are too large or too small for its underlying representation.
- Implementation: Perform input validation on any numeric input by ensuring that it is within the expected range. Enforce that the input meets both the minimum and maximum requirements for the expected range.
- Implementation: Use the appropriate type for the desired action. For example, in C/C++, only use unsigned types for values that could never be negative, such as height, width, or other numbers related to quantity.
- Architecture and Design: Use languages, libraries, or frameworks that make it easier to handle numbers without unexpected consequences. Examples include safe integer handling packages such as SafeInt (C++) or IntegerLib (C or C++).
- Architecture and Design: Use languages, libraries, or frameworks that make it easier to handle numbers without unexpected consequences. Examples include safe integer handling packages such as SafeInt (C++) or IntegerLib (C or C++).
- Implementation: Examine compiler warnings closely and eliminate problems with potential security implications, such as signed / unsigned mismatch in memory operations, or use of uninitialized variables. Even if the weakness is rarely exploitable, a single failure may lead to the compromise of the entire system.
References
Advisories
Packages
Other links
Timeline
- Published
- Last updated by the source
- Latest EPSS score
Related advisories
| Advisory | Severity | Why it's related |
|---|---|---|
| GHSA-2r3x-4mrv-mcxf Vyper: Memory corruption using function calls within tuples / nested calls | Medium | Also affects vyper |
| GHSA-4v7v-gqf9-ww2g Vyper: Call stack corruption when passing complex type containing non-base type members as argument | Medium | Also affects vyper |
| GHSA-vg88-3v92-rjx2 Vyper: Return inside for loop more than 1 level deep | Low | Also affects vyper |
| GHSA-3vcg-j39x-cwfm Vyper's `slice()` may elide side-effects when output length is 0 | Low | Also affects vyper |
| GHSA-qhr6-mgqr-mchm Vyper's `concat()` builtin may elide side-effects for zero-length arguments | Low | Also affects vyper |
| GHSA-h33q-mhmp-8p67 Vyper has a double eval in For List Iter | High | Also affects vyper |
| GHSA-4w26-8p97-f4jp AugAssign evaluation order causing OOB write within the object in Vyper | Critical | Also affects vyper |
| GHSA-vgf2-gvx8-xwc3 Vyper Does Not Check the Success of Certain Precompile Calls | High | Also affects vyper |
MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.
Check your repos with MergeHarbor