EDK II - 1-Byte OOB Heap Read in IPv6 Options Validator in Ip6IsOptionValid
Ip6IsOptionValid iterates over TLV-encoded options in IPv6 Hop-by-Hop and Destination Options extension headers using a loop guarded only by while (Offset < OptionLen).
- Advisory
- BYTERAY-2026-0268
- CWE
- CWE-823
- Vendor
- TianoCore
- Product
- EDK II
- Reported
- 2026-06-25
- Disclosure
- 2026-10-29
- Affected
- EDK II at commit 70741a15d9a714323a5598eac47727e60507e22f (master, 2026-06-21); affected code in NetworkPkg/Ip6Dxe/Ip6Option.c.
- Credit
- Argus-Systems
Executive Summary
Ip6IsOptionValid iterates over TLV-encoded options in IPv6 Hop-by-Hop and Destination Options extension headers using a loop guarded only by while (Offset < OptionLen). This guard guarantees only that the Type byte at Option + Offset is within bounds. When Offset == OptionLen - 1 (reachable by filling the option area with Pad1 options to walk the cursor to the last byte), the code reads the IP6_OPTION_HEADER.Length field at Option + Offset + 1 — exactly 1 byte past the valid option area. This occurs in both the PadN case (line 79) and the default/Ip6OptionSkip case (line 95). The Router Alert case (line 86) only advances Offset by 4 and reads nothing. When the Hop-by-Hop or Destination Options header is the last data in the received payload, the extra byte lies past the end of the pool block holding the payload; otherwise it is the next header's first byte in the same buffer. The sibling function Ip6IsNDOptionValid (same file, line 179) correctly guards with while (Offset + sizeof(IP6_OPTION_HEADER) - 1 < OptionLen), confirming the discrepancy is a genuine bug.
This advisory is one of a set reported to VulnCheck on 2026-06-25 for coordinated disclosure to the EDK II maintainers. After several follow-ups over the following months no response was received. 126 days after the initial report, ByteRay is publishing the findings in good faith so that affected integrators can assess and remediate them. All findings were identified against EDK II commit 70741a15d9a714323a5598eac47727e60507e22f (master, 2026-06-21).
Affected Products and Versions
- Vendor: TianoCore
- Product: EDK II (
NetworkPkg) - Affected commit:
70741a15d9a714323a5598eac47727e60507e22f(master, 2026-06-21). The code is present on that commit and later revisions that have not changed it. - Location:
NetworkPkg/Ip6Dxe/Ip6Option.c:79,NetworkPkg/Ip6Dxe/Ip6Option.c:95 - Function:
Ip6IsOptionValid - Category:
Use of Out-of-Range Pointer Offset (CWE-823)
Technical Details
Controllability: EXTERNAL_UNTRUSTED — confidence: high
Data Flow
A remote IPv6 frame is received via the MNP receive callback Ip6AcceptFrame (Ip6Input.c:976). The payload is tightly allocated with AllocatePool(PayloadLen) and filled with exactly PayloadLen bytes via NetbufCopy (Ip6Input.c:845–850). The extension header data is passed to Ip6IsExtsValid (Ip6Input.c:853), which computes OptionLen = IP6_HDR_EXT_LEN(*Option) - sizeof(IP6_EXT_HDR) from the attacker-controlled Hdr Ext Len byte (Ip6Option.c:455) and calls Ip6IsOptionValid (Ip6Option.c:459). The loop guard while (Offset < OptionLen) (Ip6Option.c:65) only ensures the Type byte at Option + Offset is in-bounds. When Offset == OptionLen - 1, reading ->Length at Option + Offset + 1 (Ip6Option.c:79 or :95) accesses 1 byte past the option area, which is 1 byte past the allocated pool block when the options header ends at the end of the payload. The byte read only decides the next Offset and therefore whether the loop exits; it is not returned or copied anywhere.
Affected Callers
Ip6IsExtsValid(Ip6Option.c:459)Ip6PreProcessPacket(Ip6Input.c:853, 937), on the network receive pathIp6InstanceFrameAcceptable(Ip6Input.c:1305, 1340)Ip6Output(Ip6Output.c:536, 657), withRcvd = FALSEand extension headers supplied by the local caller rather than the network
Sanitization / Security Controls
None. The loop guard while (Offset < OptionLen) at line 65 is the only check and it is insufficient — it does not account for the 2-byte Type+Length header.
Reachability and Preconditions
Attacker position and trust level for this issue are stated in the Controllability line and Data Flow above, and the concrete trigger is in Reproduction below.
Exploitability: Medium
Realism: Medium
Reproduction
- Attacker can send IPv6 packets to the target interface (network adjacency); target device has IPv6 networking enabled (Ip6Dxe driver loaded).
- Craft an IPv6 packet with a Hop-by-Hop (Next Header 0) or Destination Options (Next Header 60) extension header as the last data in the payload (its own Next Header 59, no further data). Set Hdr Ext Len so
OptionLen = (HdrExtLen+1)*8 - 2. - Fill the option area with Pad1 (0x00) bytes up to offset
OptionLen - 1, then place PadN (0x01) or an unrecognized option type whose two high bits are 00 at the last position. - Send the packet. The
->Lengthread at offsetOptionLenis 1 byte past the payload pool block.
Impact
1-byte out-of-bounds heap read triggered by an unauthenticated on-link IPv6 sender. The byte only influences the loop exit and is never returned, so nothing leaks. In a normal build the byte is pool tail or alignment padding; with a tail-aligned heap guard enabled the read faults and crashes the firmware.
Remediation and Mitigation
As of commit 70741a15d9a714323a5598eac47727e60507e22f this issue is unfixed upstream and no CVE has been assigned. Validate that the full field width fits within the remaining buffer before dereferencing the pointer offset. The specific control that is absent or ineffective is identified in the Sanitization / Security Controls list under Technical Details.
Timeline
- 2026-06-25 - Reported to VulnCheck for coordinated disclosure to the TianoCore / EDK II security team.
- 2026-07 to 2026-10 - Several follow-ups sent; no response received.
- 2026-10-29 - Public disclosure in good faith, 126 days after the initial report.
Credits
Discovered and reported by Argus-Systems.