CVE-2026-78119: Out-of-bounds write in the Nuvoton NPCX eSPI Target-Attached-Flash receive path from an unvalidated host-supplied packet length
The Nuvoton NPCX eSPI driver parses Target-Attached-Flash (TAF) requests in espitafparse() (drivers/espi/espinpcx.c), taking the 12-bit length field directly out of the request header in the FLASHRXBUF FIFO. For write and RPMC OP1 requests it copied DIVROUNDUP(len, 4) words into struct espitafpckt.src, a fixed 16-word (64-byte) member of a static structure, without ever comparing the length against that buffer or against the negotiated eSPI receive payload size (rx-plsize, 64 bytes on all in-tree NPCX/NPCK SoCs). Both the loop counter and the word count were uint8t, so the copy ran up to 255 iterations.
An eSPI controller that emits a flash request whose header claims a payload larger than the negotiated maximum therefore drives up to 239 32-bit stores past the end of the structure — roughly 956 bytes of out-of-bounds write into .bss — from the eSPI flash receive interrupt handler, while the source reads walk past the end of the 18-word FLASHRXBUF register array into neighbouring eSPI registers. The same unvalidated length was then passed on to flashwrite() in espitafnpcxflashwrite() with the 64-byte src buffer as source, reading up to 4 KB of adjacent controller SRAM into SPI flash at a host-chosen address, where the host can read it back. A related fixed-size stack buffer in tafnpcxcompletionhandler() was overflowed by four bytes on the maximum-size completion path on SoCs whose tx-plsize is 64.
The defect is reachable only from the eSPI host side, and only by a request that violates the negotiated payload size, so it requires host firmware or bus-level control rather than ordinary host software; a compliant maximum-length write fits the buffer exactly and is handled correctly. Because TAF exists specifically so that the embedded controller arbitrates host access to shared flash (espitafcheckreadprotect() / espitafcheckwriteprotect()), corrupting controller memory from a host-supplied field crosses the trust boundary the feature asserts; consequences range from controller crash or hang to corruption of driver state that gates the flash protection regions.
The fix widens the counters, rejects any request whose word count exceeds both ARRAYSIZE(FLASHRXBUF) - NPCXESPIFLASHHEADERADDRESSLEN and NPCXTAFRXPAYLOADWORDS (derived from the devicetree rx-plsize), marks such packets with a new invalidflag so espitafwork() answers them with an unsuccessful completion instead of processing them, bounds the transmit payload against FLASHTXBUF, and adds a default case for unsupported cycle types. Only configurations with CONFIGESPITAF enabled on an NPCX/NPCK target are affected; no in-tree board enables it by default.
Affected Software
Event History
Frequently Asked Questions
What access does an attacker need to trigger this issue?
An attacker needs control of an eSPI controller that can send Target-Attached-Flash requests to the NPCX device. The vulnerable handling occurs in the eSPI flash receive interrupt path and does not require user interaction.
Which request types can cause the unsafe copy?
Write and RPMC OP1 Target-Attached-Flash requests use the host-supplied length to determine how many words are copied into a fixed 64-byte source buffer. A claimed payload larger than the negotiated maximum can cause writes beyond that buffer.
Is the negotiated eSPI receive payload limit sufficient protection?
No. Although rx-plsize is 64 bytes on the described in-tree NPCX/NPCK SoCs, the affected code did not compare the request length with either the 64-byte buffer size or the negotiated receive payload size.
What are the potential consequences after the out-of-bounds copy?
The interrupt handler can write up to 239 32-bit words past the static structure into adjacent .bss memory. The unchecked length is also passed to flash_write() with the 64-byte buffer as its source, potentially causing reads of adjacent controller SRAM.