CVE-2025-47285
Executive Summary
CVE-2025-47285 is a vulnerability in the Vyper programming language, a Pythonic language for the Ethereum Virtual Machine (EVM). The flaw resides in the concat() built-in function, where side effects from argument expressions may be skipped if the length of the argument is zero. This occurs due to a fastpath optimization that bypasses evaluation of expressions when their length is zero. In practice, this is unlikely to be exploited in typical user code, as zero-length bytestrings are usually constructed with the empty literal b"". However, the introduction of the ternary operator in v0.3.8 allows for the creation of empty bytestrings with side effects (e.g., b"" if self.do_some_side_effect() else b""). The vulnerability could lead to unexpected behavior in smart contracts, potentially affecting state changes or event emissions.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
Vyper is a critical component in the Ethereum ecosystem, used to write smart contracts. This vulnerability affects the Vyper compiler itself, not a package manager like PyPI. However, any smart contract compiled with a vulnerable version of Vyper could be affected. Developers should ensure they are using a patched version of the compiler to avoid introducing this bug into their contracts.
CVSS Breakdown & Threat Level
The CVSS score is 0.0, indicating that no official CVSS vector has been assigned. However, based on the nature of the vulnerability, a reasonable assessment would be:
- Attack Vector (AV): Network (N) - The vulnerability is in the compiler, but exploitation would require a crafted contract to be deployed.
- Attack Complexity (AC): High (H) - Exploitation requires specific conditions (side effects in zero-length bytestring expressions).
- Privileges Required (PR): None (N) - No privileges needed to deploy a contract.
- User Interaction (UI): None (N) - No user interaction required.
- Scope (S): Unchanged (U) - The vulnerability affects the contract's behavior, not the compiler itself.
- Confidentiality (C): None (N) - No data exposure.
- Integrity (I): Low (L) - Potential for unexpected state changes.
- Availability (A): None (N) - No denial of service.
Threat Level: Low. The vulnerability is difficult to exploit and requires specific coding patterns.
Deep Dive & Mechanics
The concat() function in Vyper is used to concatenate multiple bytestrings. The implementation includes a fastpath that checks if the length of an argument is zero. If so, it skips the evaluation of the argument expression to save gas. This optimization is flawed because it does not account for side effects that may occur during the evaluation of the expression.
For example, consider the following Vyper code:
@external
def foo() -> Bytes[100]:
return concat(b"" if self.do_some_side_effect() else b"", b"other")
In this case, self.do_some_side_effect() is expected to be called, but due to the fastpath, it may be skipped if the length of the first argument is zero. This could lead to unexpected behavior, such as missing state updates or event emissions.
The vulnerability affects versions up to and including 0.4.2rc1. The fix is available in pull request 4644 and is expected to be part of the 0.4.2 release.
Vulnerable vs. Patched Code
Vulnerable Code (Vyper <= 0.4.2rc1):
# In the concat implementation, there is a fastpath that skips evaluation
# of arguments with zero length. This is the vulnerable behavior.
@internal
def concat(*args: BytesLike) -> Bytes:
result: Bytes = b""
for arg in args:
if len(arg) == 0:
# Fastpath: skip evaluation of zero-length arguments
continue
result = result + arg
return result
Patched Code (Vyper >= 0.4.2):
# The patched version ensures that all arguments are evaluated,
# even if their length is zero.
@internal
def concat(*args: BytesLike) -> Bytes:
result: Bytes = b""
for arg in args:
# Always evaluate the argument, even if length is zero
evaluated_arg = arg
if len(evaluated_arg) == 0:
continue
result = result + evaluated_arg
return result
Exploitation & Lab Setup
Red Team
To exploit this vulnerability, an attacker would need to deploy a smart contract that uses concat() with a zero-length bytestring expression that has side effects. The attacker could then observe that the side effects are not executed, leading to unexpected behavior.
Lab Setup:
- Install a vulnerable version of Vyper (e.g., 0.4.2rc1).
- Create a Vyper contract with a function that uses
concat()with a ternary operator to create a zero-length bytestring with side effects. - Deploy the contract to a local Ethereum testnet (e.g., Ganache).
- Call the function and observe that the side effects are not executed.
Example Exploit Contract:
# exploit.vy
@external
def trigger_side_effect() -> Bytes[100]:
# This should call self.do_something(), but due to the bug, it may not
return concat(b"" if self.do_something() else b"", b"test")
@internal
def do_something() -> bool:
# Side effect: emit an event or modify state
self.some_state = True
return True
Blue Team
To detect exploitation attempts, monitor for contracts that use concat() with complex expressions that could have side effects. Additionally, review contract bytecode for patterns that indicate the use of the vulnerable fastpath.
Detection Steps:
- Scan contract source code for
concat()calls with ternary operators or other expressions that could produce zero-length bytestrings. - Analyze contract bytecode for the presence of the fastpath optimization.
- Monitor for unexpected behavior in contracts that use
concat().
Indicators of Compromise (IOCs)
- Contract Bytecode Pattern: Presence of the fastpath optimization in
concat()implementation. - Source Code Pattern: Use of
concat()with ternary operators or other expressions that could produce zero-length bytestrings. - Behavioral IOC: Unexpected missing side effects in contracts that use
concat().
Detection Engineering
YARA Rule
rule CVE_2025_47285_Vyper_Concat_Fastpath {
meta:
description = "Detects Vyper contracts with vulnerable concat() fastpath"
author = "Valters IT"
date = "2025-04-10"
cve = "CVE-2025-47285"
strings:
$fastpath = /concat\s*\([^)]*\)/ nocase
$ternary = /b""\s+if\s+/ nocase
condition:
$fastpath and $ternary
}
Sigma Rule
title: CVE-2025-47285 Vyper Concat Side Effect Bypass
id: 12345678-1234-1234-1234-123456789012
status: experimental
description: Detects Vyper contracts that may be vulnerable to CVE-2025-47285
author: Valters IT
date: 2025-04-10
logsource:
category: smart_contract
product: vyper
detection:
selection:
SourceCode|contains: 'concat('
SourceCode|contains: 'b"" if '
condition: selection
falsepositives:
- Legitimate use of ternary operators with empty bytestrings
level: low
Suricata Rule
alert tcp any any -> any any (msg:"CVE-2025-47285 Vyper Concat Side Effect Bypass"; content:"concat("; content:"b"" if "; classtype:attempted-admin; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Mitigation:
- Avoid using side effects in expressions that construct zero-length bytestrings.
- Review all
concat()calls in your Vyper contracts for potential side effects.
Permanent Fix:
- Upgrade to Vyper version 0.4.2 or later, which includes the fix from pull request 4644.
- Recompile all contracts with the patched compiler.
Workaround:
- If upgrading is not possible, refactor code to avoid using
concat()with zero-length bytestring expressions that have side effects.
Valters IT
DevSecOps & Cyber Threat Intelligence Expert