---
id: "CVE-2026-114663"
kind: "vulnerability"
aliases: ["CVE-2026-114663"]
title: "Vyper compiler: imported constants resolve to wrong variable, corrupting contract logic"
severity: "high"
cvss: 8.6
epss: 0.00136
exploited: false
status: "open"
category: "package"
products: [{"name": "vyper", "fixed": [], "affected": ">= 0.4.0b1, <= 0.5.0b1 (and master 17e925db)", "ecosystem": "pip"}]
ecosystems: ["pip"]
tags: ["compiler", "ethereum", "package", "smart-contracts", "vyper"]
not_affected_if: ["constants-fully-folded", "no-imported-modules", "no-imported-modules-with-constants", "no-name-collision", "vyper-above-0.5.0b1", "vyper-below-0.4.0b1"]
published_at: "2026-10-22T02:16:58+00:00"
first_seen_at: "2026-10-23T21:57:30+00:00"
updated_at: "2026-10-24T07:15:52+00:00"
sources: [{"source": "nvd", "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-114663", "first_seen_at": "2026-10-23T21:57:30+00:00"}, {"source": "analyst", "url": null, "first_seen_at": "2026-10-23T23:45:19+00:00"}, {"source": "epss", "url": "https://api.first.org/data/v1/epss?cve=CVE-2026-114663", "first_seen_at": "2026-10-24T07:15:52+00:00"}]
---

# Vyper compiler: imported constants resolve to wrong variable, corrupting contract logic

Vyper >=0.4.0b1 (through 0.5.0b1 and master) compiles unfoldable imported constants and omitted default arguments in the using function's scope. A same-named parameter, local or loop variable from the calling contract replaces the intended value, even pushing out-of-range values into narrow types like uint8. The colliding declaration must be in an imported module, and the replaced expression must stay unfoldable. An external user controls the value only if the captured variable derives from user input. No patched release exists yet.

_Summary, check and fix written by a model from the sources; labelled as such._

## Affected

- pip:vyper affected >= 0.4.0b1, <= 0.5.0b1 (and master 17e925db) fixed ?

## How to check

Check the compiler version used to build your contracts: vyper --version, or pip show vyper (0.4.0b1 and later is affected). Then, in any contract that imports a module, look for imported constants (constant(...) not fully folded to literals) or default arguments (x: uint8 = E) whose names or inner names match a parameter, local or loop variable in the calling function. The PoC in the advisory shows the pattern: test(300) returns 300 instead of 0. Deployed bytecode must be recompiled to fix.

## Fix

No fixed version as of 2026-10-23: the advisory says Patched versions: None. Workaround: use literal or fully folded values, or rename so no name collides anywhere in the expanded expressions. Passing a qualified immutable explicitly avoids default capture, but qualifying an unfoldable constant alone is not enough. Already deployed contracts need recompiling and redeploying or upgrading once a fix ships. Watch GHSA-2489-32vh-8rrc.

## Timeline

- 2026-10-23T21:57:30+00:00 nvd https://nvd.nist.gov/vuln/detail/CVE-2026-114663
- 2026-10-23T23:45:19+00:00 analyst — Read GHSA-2489-32vh-8rrc (maintainer, Oct 7): no patched version; affects >=0.4.0b1 through master 17e925db. Latest release v0.5.0b1 is affected per CVE. PoC is inline in the advisory; no exploitation reported; no X chatter. GitHub rates it Moderate, CVE/VulnCheck 8.6 High; severity left unchanged.
- 2026-10-24T07:15:52+00:00 epss https://api.first.org/data/v1/epss?cve=CVE-2026-114663

## Documents

- [advisory] GHSA-2489-32vh-8rrc: Function variables can replace imported constant values and default arguments https://github.com/vyperlang/vyper/security/advisories/GHSA-2489-32vh-8rrc
- [advisory] VulnCheck: Vyper 0.4.0b1 through 0.5.0b1 Name Shadowing https://www.vulncheck.com/advisories/vyper-0.4-0b1-through-0.5-0b1-name-shadowing-of-imported-constants-and-default-arguments
- [mentions] vyperlang/vyper releases (latest v0.5.0b1) https://github.com/vyperlang/vyper/releases

## From the sources

Vyper 0.4.0b1 through 0.5.0b1 miscompiles unfoldable constants and omitted default arguments from imported modules, because parse_Name resolves their names in the using function's scope rather than at declaration. When a contract's parameter, local, or loop variable shares such a name, attacker-influenced input can replace the intended value, including out-of-range values for narrow types such as uint8, corrupting validation or accounting logic.

---

_Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai_
