CVE-2025-54070
OpenZeppelin Contracts's Bytes's lastIndexOf function with position argument performs out-of-bound memory access on empty buffers
OpenZeppelin Contracts is a library for secure smart contract development. Starting in version 5.2.0 and prior to version 5.4.0, the lastIndexOf(bytes,byte,uint256) function of the Bytes.sol library may access uninitialized memory when the following two conditions hold: 1) the provided buffer length is empty (i.e. buffer.length == 0) and position is not 2**256 - 1 (i.e. pos != type(uint256).max). The pos argument could be used to access arbitrary data outside of the buffer bounds. This could lead to the operation running out of gas, or returning an invalid index (outside of the empty buffer). Processing this invalid result for accessing the buffer would cause a revert under normal conditions. When triggered, the function reads memory at offset buffer + 0x20 + pos. If memory at that location (outside the buffer) matches the search pattern, the function would return an out of bound index instead of the expected type(uint256).max. This creates unexpected behavior where callers receive a valid-looking index pointing outside buffer bounds. Subsequent memory accesses that don't check bounds and use the returned index must carefully review the potential impact depending on their setup. Code relying on this function returning type(uint256).max for empty buffers or using the returned index without bounds checking could exhibit undefined behavior. Users should upgrade to version 5.4.0 to receive a patch.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- None
- Integrity
- Low
- Availability
- Low
Exploit likelihood
What each source reports
CVE List Score used
6.9
OpenZeppelin Contracts's Bytes's lastIndexOf function with position argument performs out-of-bound memory access on empty buffers
OpenZeppelin Contracts is a library for secure smart contract development. Starting in version 5.2.0 and prior to version 5.4.0, the lastIndexOf(bytes,byte,uint256) function of the Bytes.sol library may access uninitialized memory when the following two conditions hold: 1) the provided buffer length is empty (i.e. buffer.length == 0) and position is not 2**256 - 1 (i.e. pos != type(uint256).max). The pos argument could be used to access arbitrary data outside of the buffer bounds. This could lead to the operation running out of gas, or returning an invalid index (outside of the empty buffer). Processing this invalid result for accessing the buffer would cause a revert under normal conditions. When triggered, the function reads memory at offset buffer + 0x20 + pos. If memory at that location (outside the buffer) matches the search pattern, the function would return an out of bound index instead of the expected type(uint256).max. This creates unexpected behavior where callers receive a valid-looking index pointing outside buffer bounds. Subsequent memory accesses that don't check bounds and use the returned index must carefully review the potential impact depending on their setup. Code relying on this function returning type(uint256).max for empty buffers or using the returned index without bounds checking could exhibit undefined behavior. Users should upgrade to version 5.4.0 to receive a patch.
- Record
CVE-2025-54070- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:L/SC:N/SI:N/SA:N - Weakness
- CWE-125
- Updated
- 2026-11-02
EUVDEUVD-2025-21789
6.9
OpenZeppelin Contracts is a library for secure smart contract development. Starting in version 5.2.0 and prior to version 5.4.0, the lastIndexOf(bytes,byte,uint256) function of the Bytes.sol library may access uninitialized memory when the following two conditions hold: 1) the provided buffer length is empty (i.e. buffer.length == 0) and position is not 2**256 - 1 (i.e. pos != type(uint256).max). The pos argument could be used to access arbitrary data outside of the buffer bounds. This could lead to the operation running out of gas, or returning an invalid index (outside of the empty buffer). Processing this invalid result for accessing the buffer would cause a revert under normal conditions. When triggered, the function reads memory at offset buffer + 0x20 + pos. If memory at that location (outside the buffer) matches the search pattern, the function would return an out of bound index instead of the expected type(uint256).max. This creates unexpected behavior where callers receive a valid-looking index pointing outside buffer bounds. Subsequent memory accesses that don't check bounds and use the returned index must carefully review the potential impact depending on their setup. Code relying on this function returning type(uint256).max for empty buffers or using the returned index without bounds checking could exhibit undefined behavior. Users should upgrade to version 5.4.0 to receive a patch.
- Record
EUVD-2025-21789- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:L/SC:N/SI:N/SA:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-9rcw-c2f9-2j55
6.9
OpenZeppelin Contracts Bytes's lastIndexOf function with position argument performs out-of-bound memory access on empty buffers
Impact
The lastIndexOf(bytes,byte,uint256) function of the Bytes.sol library may access uninitialized memory when the following two conditions hold: 1) the provided buffer length is empty (i.e. buffer.length == 0) and position is not 2**256 - 1 (i.e. pos != type(uint256).max).
The pos argument could be used to access arbitrary data outside of the buffer bounds. This could lead to the operation running out of gas, or returning an invalid index (outside of the empty buffer). Processing this invalid result for accessing the buffer would cause a revert under normal conditions.
When triggered, the function reads memory at offset buffer + 0x20 + pos. If memory at that location (outside the buffer) matches the search pattern, the function would return an out of bound index instead of the expected type(uint256).max. This creates unexpected behavior where callers receive a valid-looking index pointing outside buffer bounds.
Subsequent memory accesses that don't check bounds and use the returned index must carefully review the potential impact depending on their setup. Code relying on this function returning type(uint256).max for empty buffers or using the returned index without bounds checking could exhibit undefined behavior.
Patches
Upgrade to 5.4.0
- Record
GHSA-9rcw-c2f9-2j55- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:L/SC:N/SI:N/SA:N - CVSS 3.1
- 0.0 None
CVSS:3.1/AV:L/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:N - Weakness
- CWE-125
- Updated
- 2026-11-02
NVD
6.9
OpenZeppelin Contracts is a library for secure smart contract development. Starting in version 5.2.0 and prior to version 5.4.0, the lastIndexOf(bytes,byte,uint256) function of the Bytes.sol library may access uninitialized memory when the following two conditions hold: 1) the provided buffer length is empty (i.e. buffer.length == 0) and position is not 2**256 - 1 (i.e. pos != type(uint256).max). The pos argument could be used to access arbitrary data outside of the buffer bounds. This could lead to the operation running out of gas, or returning an invalid index (outside of the empty buffer). Processing this invalid result for accessing the buffer would cause a revert under normal conditions. When triggered, the function reads memory at offset buffer + 0x20 + pos. If memory at that location (outside the buffer) matches the search pattern, the function would return an out of bound index instead of the expected type(uint256).max. This creates unexpected behavior where callers receive a valid-looking index pointing outside buffer bounds. Subsequent memory accesses that don't check bounds and use the returned index must carefully review the potential impact depending on their setup. Code relying on this function returning type(uint256).max for empty buffers or using the returned index without bounds checking could exhibit undefined behavior. Users should upgrade to version 5.4.0 to receive a patch.
- Record
CVE-2025-54070- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - Weakness
- CWE-125
- Updated
- 2026-11-02
OSV
6.9
OpenZeppelin Contracts's Bytes's lastIndexOf function with position argument performs out-of-bound memory access on empty buffers
OpenZeppelin Contracts is a library for secure smart contract development. Starting in version 5.2.0 and prior to version 5.4.0, the lastIndexOf(bytes,byte,uint256) function of the Bytes.sol library may access uninitialized memory when the following two conditions hold: 1) the provided buffer length is empty (i.e. buffer.length == 0) and position is not 2**256 - 1 (i.e. pos != type(uint256).max). The pos argument could be used to access arbitrary data outside of the buffer bounds. This could lead to the operation running out of gas, or returning an invalid index (outside of the empty buffer). Processing this invalid result for accessing the buffer would cause a revert under normal conditions. When triggered, the function reads memory at offset buffer + 0x20 + pos. If memory at that location (outside the buffer) matches the search pattern, the function would return an out of bound index instead of the expected type(uint256).max. This creates unexpected behavior where callers receive a valid-looking index pointing outside buffer bounds. Subsequent memory accesses that don't check bounds and use the returned index must carefully review the potential impact depending on their setup. Code relying on this function returning type(uint256).max for empty buffers or using the returned index without bounds checking could exhibit undefined behavior. Users should upgrade to version 5.4.0 to receive a patch.
- Record
CVE-2025-54070- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:L/SC:N/SI:N/SA:N - Weakness
- CWE-125
- Updated
- 2026-11-02
OSVGHSA-9rcw-c2f9-2j55
6.9
OpenZeppelin Contracts Bytes's lastIndexOf function with position argument performs out-of-bound memory access on empty buffers
Impact
The lastIndexOf(bytes,byte,uint256) function of the Bytes.sol library may access uninitialized memory when the following two conditions hold: 1) the provided buffer length is empty (i.e. buffer.length == 0) and position is not 2**256 - 1 (i.e. pos != type(uint256).max).
The pos argument could be used to access arbitrary data outside of the buffer bounds. This could lead to the operation running out of gas, or returning an invalid index (outside of the empty buffer). Processing this invalid result for accessing the buffer would cause a revert under normal conditions.
When triggered, the function reads memory at offset buffer + 0x20 + pos. If memory at that location (outside the buffer) matches the search pattern, the function would return an out of bound index instead of the expected type(uint256).max. This creates unexpected behavior where callers receive a valid-looking index pointing outside buffer bounds.
Subsequent memory accesses that don't check bounds and use the returned index must carefully review the potential impact depending on their setup. Code relying on this function returning type(uint256).max for empty buffers or using the returned index without bounds checking could exhibit undefined behavior.
Patches
Upgrade to 5.4.0
- Record
GHSA-9rcw-c2f9-2j55- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:L/SC:N/SI:N/SA:N - CVSS 3.1
- 0.0 None
CVSS:3.1/AV:L/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:N - Weakness
- CWE-125
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
@openzeppelin/contractsnpm |
5.2.0 up to 5.4.0 | 5.4.0 |
@openzeppelin/contracts-upgradeablenpm |
5.2.0 up to 5.4.0 | 5.4.0 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2025-54070 is a medium vulnerability (CVSS 6.9) in Openzeppelin Openzeppelin-contracts, published July 17, 2025. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.40%, the 34th percentile. Fixed in @openzeppelin/contracts 5.4.0.
References
github.com/OpenZeppelin/openzeppelin-contracts/security/advisories/GHSA-9rcw-c2f9-2j55
github.com/OpenZeppelin/openzeppelin-contracts/releases/tag/v5.4.0
github.com/OpenZeppelin/openzeppelin-contracts/pull/5797
nvd.nist.gov/vuln/detail/CVE-2025-54070
github.com/advisories/GHSA-9rcw-c2f9-2j55
github.com/CVEProject/cvelistV5/tree/main/cves/2025/54xxx/CVE-2025-54070.json
github.com/OpenZeppelin/openzeppelin-contracts