osec-2026-02
Vulnerability from osv_ocaml
Background
Mirage's implementation of the ARP protocol (RFC826) caches ARP replies to construct an IPv4 address -> MAC address cache. This cache is long-lived (effectively global), and also contains pending ARP requests, which are replaced by the reply, or deleted after a timeout. ARP replies that do not match any entry in the ARP cache are ignored (dropped).
The maximum amount of memory that a Solo5 unikernel can be assigned is 4GiB (see X86_GUEST_MAX_SIZE and AARCH64_MMIO_BASE).
Problem description
There are no no size constraints on the cache, and with 2^32 IPv4 addresses, it can exceed the maximum amount of memory that can be allocated by a unikernel if an attacker has Layer-2 access to that unikernel and can spoof arbitrary IP addresses. An attacker also needs to trick the unikernel into sending out an ARP query (ARP replies that don't have a corresponding Pending or Dynamic entry in the ARP table are ignored), this can be done by spoofing an ICMP echo request for example. However while attempting to develop an exploit for this another vulnerability was discovered (reported separately).
Impact
All versions of 'arp' are affected, and this module is typically used by a unikernel that provides network services. An affected unikernel can crash with an Out of memory condition. Unikernels that do not have network devices are not affected.
Workaround
Devices on the same network/bridge as a unikernel should have firewall rules (on their TAP devices) that prevent sending ARP packets with IPv4 addresses that the unikernel doesn't own (although this becomes difficult to enforce if DHCP is used).
Unikernel orchestrators can be configured to restart unikernels on crash, although you'd still lose any state that was in memory.
Solution
Use a cache with a fixed upper bound on size, e.g. a LRU cache that drops old entries.
Timeline
2025-05-23: issue discovered by Edwin Török while reviewing code to debug another OOM crash as part of the HACKSAT25 challenge 2025-05-28: issue reported to security@mirage.io 2025-10-20: arp 4.1.0 was released 2026-02-18: security advisory was published
{
"affected": [
{
"ecosystem_specific": {
"opam_constraint": "arp {\u003c \"4.1.0\"}"
},
"package": {
"ecosystem": "opam",
"name": "arp",
"purl": "pkg:opam/arp"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "4.1.0"
}
],
"type": "ECOSYSTEM"
},
{
"events": [
{
"introduced": "0"
},
{
"fixed": "a700d9f139a387839172dde816660472023cb13f"
}
],
"repo": "https://github.com/mirage/arp",
"type": "GIT"
}
],
"versions": [
"0.1.1",
"0.2.0",
"0.2.1",
"0.2.2",
"0.2.3",
"1.0.0",
"2.0.0",
"2.1.0",
"2.2.0",
"2.2.1",
"2.3.1",
"2.3.2",
"3.0.0",
"3.1.0",
"3.1.1",
"4.0.0"
]
}
],
"credits": [
{
"name": "Edwin T\u00f6r\u00f6k",
"type": "REPORTER"
},
{
"name": "Edwin T\u00f6r\u00f6k",
"type": "REMEDIATION_DEVELOPER"
},
{
"name": "Hannes Mehnert",
"type": "REMEDIATION_REVIEWER"
},
{
"name": "Romain Calascibetta",
"type": "REMEDIATION_REVIEWER"
}
],
"database_specific": {
"cwe": [
"CWE-770"
],
"human_link": "https://github.com/ocaml/security-advisories/tree/main/advisories/2026/OSEC-2026-02.md",
"osv": "https://github.com/ocaml/security-advisories/tree/generated-osv/2026/OSEC-2026-02.json"
},
"details": "## Background\n\nMirage\u0027s implementation of the ARP protocol (RFC826) caches ARP replies to construct an IPv4 address -\u003e MAC address cache. This cache is long-lived (effectively global), and also contains pending ARP requests, which are replaced by the reply, or deleted after a timeout. ARP replies that do not match any entry in the ARP cache are ignored (dropped).\n\nThe maximum amount of memory that a Solo5 unikernel can be assigned is 4GiB (see X86_GUEST_MAX_SIZE and AARCH64_MMIO_BASE).\n\n## Problem description\n\nThere are no no size constraints on the cache, and with 2^32 IPv4 addresses, it can exceed the maximum amount of memory that can be allocated by a unikernel if an attacker has Layer-2 access to that unikernel and can spoof arbitrary IP addresses. An attacker also needs to trick the unikernel into sending out an ARP query (ARP replies that don\u0027t have a corresponding Pending or Dynamic entry in the ARP table are ignored), this can be done by spoofing an ICMP echo request for example. However while attempting to develop an exploit for this another vulnerability was discovered (reported separately).\n\n## Impact\n\nAll versions of \u0027arp\u0027 are affected, and this module is typically used by a unikernel that provides network services. An affected unikernel can crash with an Out of memory condition. Unikernels that do not have network devices are not affected.\n\n## Workaround\n\nDevices on the same network/bridge as a unikernel should have firewall rules (on their TAP devices) that prevent sending ARP packets with IPv4 addresses that the unikernel doesn\u0027t own (although this becomes difficult to enforce if DHCP is used).\n\nUnikernel orchestrators can be configured to restart unikernels on crash, although you\u0027d still lose any state that was in memory.\n\n## Solution\n\nUse a cache with a fixed upper bound on size, e.g. a LRU cache that drops old entries.\n\n## Timeline\n\n2025-05-23: issue discovered by Edwin T\u00f6r\u00f6k while reviewing code to debug another OOM crash as part of the HACKSAT25 challenge\n2025-05-28: issue reported to security@mirage.io\n2025-10-20: arp 4.1.0 was released\n2026-02-18: security advisory was published",
"id": "OSEC-2026-02",
"modified": "2026-02-18T10:30:00Z",
"published": "2026-02-18T10:30:00Z",
"references": [
{
"type": "FIX",
"url": "https://github.com/mirage/arp/pull/35"
}
],
"schema_version": "1.7.4",
"severity": [
{
"score": "CVSS:3.0/AV:A/AC:L/PR:N/UI:N/S:C/C:N/I:N/A:H",
"type": "CVSS_V3"
}
],
"summary": "ARP unbounded memory usage"
}
Sightings
| Author | Source | Type | Date |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.