VYPR
Medium severity6.5NVD Advisory· Published Jun 10, 2026

CVE-2026-45160

CVE-2026-45160

Description

An out-of-bounds read in ESP-IDF's DHCP server can lead to denial of service by crashing the DHCP server task.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

An out-of-bounds read in ESP-IDF's DHCP server can lead to denial of service by crashing the DHCP server task.

Vulnerability

An out-of-bounds read vulnerability exists in the DHCP server option parser (parse_options() in components/lwip/apps/dhcpserver/dhcpserver.c) within Espressif's ESP-IDF. Versions 5.2.7, 5.3.5, 5.4.4, 5.5.4, and 6.0.1 are affected. The parser does not validate option lengths against the packet buffer, allowing a crafted DHCP request to read past the buffer's end into adjacent heap memory. This affects devices acting as DHCP servers, such as those using ESP-IDF's SoftAP.

Exploitation

An unauthenticated attacker on the same Layer-2 network as the vulnerable device can send a single, crafted DHCP broadcast request. This request triggers the out-of-bounds read in the DHCP server's option parser. No prior association with the SoftAP is required, and any client connected to an open or PSK-protected SoftAP can initiate the exploit.

Impact

Successful exploitation results in a denial of service. The out-of-bounds read can crash the lwIP/DHCP server task or corrupt its state, preventing the server from assigning IP addresses to any clients on the SoftAP. The vulnerability does not leak data to the attacker; the read bytes are consumed as option metadata.

Mitigation

This issue has been patched in ESP-IDF versions 5.2.8, 5.3.6, 5.4.5, 5.5.5, and 6.0.2. The fix involves hardening the option parser to validate option bounds before processing, ensuring that option lengths and declared payload lengths do not exceed the buffer limits [1][2][3][4].

AI Insight generated on Jun 10, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2
  • Espressif/Esp Idfreferences2 versions
    (expand)+ 1 more
    • (no CPE)
    • (no CPE)range: 5.2.7, 5.3.5, 5.4.4, 5.5.4, 6.0.1

Patches

6
fba5f995436a

fix(lwip): Fix DHCP servver OOB read issue

https://github.com/espressif/esp-idfDavid CermakApr 9, 2026via nvd-ref
1 file changed · +33 19
  • components/lwip/apps/dhcpserver/dhcpserver.c+33 19 modified
    @@ -1,5 +1,5 @@
     /*
    - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
    + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
      *
      * SPDX-License-Identifier: Apache-2.0
      */
    @@ -49,6 +49,7 @@
     #define DHCPNAK       6
     #define DHCPRELEASE   7
     
    +#define DHCP_OPTION_PAD           0
     #define DHCP_OPTION_SUBNET_MASK   1
     #define DHCP_OPTION_HOST_NAME    12
     #define DHCP_OPTION_ROUTER        3
    @@ -917,7 +918,6 @@ static void send_ack(dhcps_t *dhcps, struct dhcps_msg *m, u16_t len)
     static u8_t parse_options(dhcps_t *dhcps, u8_t *optptr, s16_t len)
     {
         ip4_addr_t client;
    -    bool is_dhcp_parse_end = false;
         struct dhcps_state s;
     
         client.addr = *((uint32_t *) &dhcps->client_address);
    @@ -932,10 +932,31 @@ static u8_t parse_options(dhcps_t *dhcps, u8_t *optptr, s16_t len)
             DHCPS_LOG("dhcps: (s16_t)*optptr = %d\n", (s16_t)*optptr);
     #endif
     
    +        if (*optptr == DHCP_OPTION_PAD) {
    +            optptr++;
    +            continue;
    +        }
    +
    +        if (*optptr == DHCP_OPTION_END) {
    +            break;
    +        }
    +
    +        if (optptr + 1 >= end) {
    +            break;
    +        }
    +
    +        u8_t opt_len = optptr[1];
    +
    +        if (optptr + 2 + opt_len > end) {
    +            break;
    +        }
    +
             switch ((s16_t) *optptr) {
     
                 case DHCP_OPTION_MSG_TYPE:	//53
    -                type = *(optptr + 2);
    +                if (opt_len >= 1) {
    +                    type = optptr[2];
    +                }
                     break;
     
     #if CONFIG_LWIP_DHCPS_REPORT_CLIENT_HOSTNAME
    @@ -966,31 +987,24 @@ static u8_t parse_options(dhcps_t *dhcps, u8_t *optptr, s16_t len)
     #endif
     
                 case DHCP_OPTION_REQ_IPADDR://50
    -                if (memcmp((char *) &client.addr, (char *) optptr + 2, 4) == 0) {
    +                if (opt_len >= 4) {
    +                    if (memcmp((char *) &client.addr, (char *) optptr + 2, 4) == 0) {
     #if DHCPS_DEBUG
    -                    DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n");
    +                        DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n");
     #endif
    -                    s.state = DHCPS_STATE_ACK;
    -                } else {
    +                        s.state = DHCPS_STATE_ACK;
    +                    } else {
     #if DHCPS_DEBUG
    -                    DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\n");
    +                        DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\n");
     #endif
    -                    s.state = DHCPS_STATE_NAK;
    +                        s.state = DHCPS_STATE_NAK;
    +                    }
                     }
     
                     break;
    -
    -            case DHCP_OPTION_END: {
    -                is_dhcp_parse_end = true;
    -            }
    -            break;
    -        }
    -
    -        if (is_dhcp_parse_end) {
    -            break;
             }
     
    -        optptr += optptr[1] + 2;
    +        optptr += opt_len + 2;
         }
     
         switch (type) {
    
8b4b5d530181

fix(lwip): Fix DHCP servver OOB read issue

https://github.com/espressif/esp-idfDavid CermakApr 9, 2026via nvd-ref
1 file changed · +33 19
  • components/lwip/apps/dhcpserver/dhcpserver.c+33 19 modified
    @@ -1,5 +1,5 @@
     /*
    - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
    + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
      *
      * SPDX-License-Identifier: Apache-2.0
      */
    @@ -49,6 +49,7 @@
     #define DHCPNAK       6
     #define DHCPRELEASE   7
     
    +#define DHCP_OPTION_PAD           0
     #define DHCP_OPTION_SUBNET_MASK   1
     #define DHCP_OPTION_HOST_NAME    12
     #define DHCP_OPTION_ROUTER        3
    @@ -917,7 +918,6 @@ static void send_ack(dhcps_t *dhcps, struct dhcps_msg *m, u16_t len)
     static u8_t parse_options(dhcps_t *dhcps, u8_t *optptr, s16_t len)
     {
         ip4_addr_t client;
    -    bool is_dhcp_parse_end = false;
         struct dhcps_state s;
     
         client.addr = *((uint32_t *) &dhcps->client_address);
    @@ -932,10 +932,31 @@ static u8_t parse_options(dhcps_t *dhcps, u8_t *optptr, s16_t len)
             DHCPS_LOG("dhcps: (s16_t)*optptr = %d\n", (s16_t)*optptr);
     #endif
     
    +        if (*optptr == DHCP_OPTION_PAD) {
    +            optptr++;
    +            continue;
    +        }
    +
    +        if (*optptr == DHCP_OPTION_END) {
    +            break;
    +        }
    +
    +        if (optptr + 1 >= end) {
    +            break;
    +        }
    +
    +        u8_t opt_len = optptr[1];
    +
    +        if (optptr + 2 + opt_len > end) {
    +            break;
    +        }
    +
             switch ((s16_t) *optptr) {
     
                 case DHCP_OPTION_MSG_TYPE:	//53
    -                type = *(optptr + 2);
    +                if (opt_len >= 1) {
    +                    type = optptr[2];
    +                }
                     break;
     
     #if CONFIG_LWIP_DHCPS_REPORT_CLIENT_HOSTNAME
    @@ -966,31 +987,24 @@ static u8_t parse_options(dhcps_t *dhcps, u8_t *optptr, s16_t len)
     #endif
     
                 case DHCP_OPTION_REQ_IPADDR://50
    -                if (memcmp((char *) &client.addr, (char *) optptr + 2, 4) == 0) {
    +                if (opt_len >= 4) {
    +                    if (memcmp((char *) &client.addr, (char *) optptr + 2, 4) == 0) {
     #if DHCPS_DEBUG
    -                    DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n");
    +                        DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n");
     #endif
    -                    s.state = DHCPS_STATE_ACK;
    -                } else {
    +                        s.state = DHCPS_STATE_ACK;
    +                    } else {
     #if DHCPS_DEBUG
    -                    DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\n");
    +                        DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\n");
     #endif
    -                    s.state = DHCPS_STATE_NAK;
    +                        s.state = DHCPS_STATE_NAK;
    +                    }
                     }
     
                     break;
    -
    -            case DHCP_OPTION_END: {
    -                is_dhcp_parse_end = true;
    -            }
    -            break;
    -        }
    -
    -        if (is_dhcp_parse_end) {
    -            break;
             }
     
    -        optptr += optptr[1] + 2;
    +        optptr += opt_len + 2;
         }
     
         switch (type) {
    
2bf4dd12002d

fix(lwip): Fix DHCP servver OOB read issue

https://github.com/espressif/esp-idfDavid CermakApr 9, 2026via nvd-ref
1 file changed · +33 19
  • components/lwip/apps/dhcpserver/dhcpserver.c+33 19 modified
    @@ -1,5 +1,5 @@
     /*
    - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
    + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
      *
      * SPDX-License-Identifier: Apache-2.0
      */
    @@ -49,6 +49,7 @@
     #define DHCPNAK       6
     #define DHCPRELEASE   7
     
    +#define DHCP_OPTION_PAD           0
     #define DHCP_OPTION_SUBNET_MASK   1
     #define DHCP_OPTION_ROUTER        3
     #define DHCP_OPTION_DNS_SERVER    6
    @@ -902,7 +903,6 @@ static void send_ack(dhcps_t *dhcps, struct dhcps_msg *m, u16_t len)
     static u8_t parse_options(dhcps_t *dhcps, u8_t *optptr, s16_t len)
     {
         ip4_addr_t client;
    -    bool is_dhcp_parse_end = false;
         struct dhcps_state s;
     
         client.addr = *((uint32_t *) &dhcps->client_address);
    @@ -917,38 +917,52 @@ static u8_t parse_options(dhcps_t *dhcps, u8_t *optptr, s16_t len)
             DHCPS_LOG("dhcps: (s16_t)*optptr = %d\n", (s16_t)*optptr);
     #endif
     
    +        if (*optptr == DHCP_OPTION_PAD) {
    +            optptr++;
    +            continue;
    +        }
    +
    +        if (*optptr == DHCP_OPTION_END) {
    +            break;
    +        }
    +
    +        if (optptr + 1 >= end) {
    +            break;
    +        }
    +
    +        u8_t opt_len = optptr[1];
    +
    +        if (optptr + 2 + opt_len > end) {
    +            break;
    +        }
    +
             switch ((s16_t) *optptr) {
     
                 case DHCP_OPTION_MSG_TYPE:	//53
    -                type = *(optptr + 2);
    +                if (opt_len >= 1) {
    +                    type = optptr[2];
    +                }
                     break;
     
                 case DHCP_OPTION_REQ_IPADDR://50
    -                if (memcmp((char *) &client.addr, (char *) optptr + 2, 4) == 0) {
    +                if (opt_len >= 4) {
    +                    if (memcmp((char *) &client.addr, (char *) optptr + 2, 4) == 0) {
     #if DHCPS_DEBUG
    -                    DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n");
    +                        DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n");
     #endif
    -                    s.state = DHCPS_STATE_ACK;
    -                } else {
    +                        s.state = DHCPS_STATE_ACK;
    +                    } else {
     #if DHCPS_DEBUG
    -                    DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\n");
    +                        DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\n");
     #endif
    -                    s.state = DHCPS_STATE_NAK;
    +                        s.state = DHCPS_STATE_NAK;
    +                    }
                     }
     
                     break;
    -
    -            case DHCP_OPTION_END: {
    -                is_dhcp_parse_end = true;
    -            }
    -            break;
    -        }
    -
    -        if (is_dhcp_parse_end) {
    -            break;
             }
     
    -        optptr += optptr[1] + 2;
    +        optptr += opt_len + 2;
         }
     
         switch (type) {
    
2da2db43fd7e

fix(lwip): Fix DHCP servver OOB read issue

https://github.com/espressif/esp-idfDavid CermakApr 9, 2026via nvd-ref
1 file changed · +33 19
  • components/lwip/apps/dhcpserver/dhcpserver.c+33 19 modified
    @@ -1,5 +1,5 @@
     /*
    - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
    + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
      *
      * SPDX-License-Identifier: Apache-2.0
      */
    @@ -49,6 +49,7 @@
     #define DHCPNAK       6
     #define DHCPRELEASE   7
     
    +#define DHCP_OPTION_PAD           0
     #define DHCP_OPTION_SUBNET_MASK   1
     #define DHCP_OPTION_ROUTER        3
     #define DHCP_OPTION_DNS_SERVER    6
    @@ -879,7 +880,6 @@ static void send_ack(dhcps_t *dhcps, struct dhcps_msg *m, u16_t len)
     static u8_t parse_options(dhcps_t *dhcps, u8_t *optptr, s16_t len)
     {
         ip4_addr_t client;
    -    bool is_dhcp_parse_end = false;
         struct dhcps_state s;
     
         client.addr = *((uint32_t *) &dhcps->client_address);
    @@ -894,38 +894,52 @@ static u8_t parse_options(dhcps_t *dhcps, u8_t *optptr, s16_t len)
             DHCPS_LOG("dhcps: (s16_t)*optptr = %d\n", (s16_t)*optptr);
     #endif
     
    +        if (*optptr == DHCP_OPTION_PAD) {
    +            optptr++;
    +            continue;
    +        }
    +
    +        if (*optptr == DHCP_OPTION_END) {
    +            break;
    +        }
    +
    +        if (optptr + 1 >= end) {
    +            break;
    +        }
    +
    +        u8_t opt_len = optptr[1];
    +
    +        if (optptr + 2 + opt_len > end) {
    +            break;
    +        }
    +
             switch ((s16_t) *optptr) {
     
                 case DHCP_OPTION_MSG_TYPE:	//53
    -                type = *(optptr + 2);
    +                if (opt_len >= 1) {
    +                    type = optptr[2];
    +                }
                     break;
     
                 case DHCP_OPTION_REQ_IPADDR://50
    -                if (memcmp((char *) &client.addr, (char *) optptr + 2, 4) == 0) {
    +                if (opt_len >= 4) {
    +                    if (memcmp((char *) &client.addr, (char *) optptr + 2, 4) == 0) {
     #if DHCPS_DEBUG
    -                    DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n");
    +                        DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n");
     #endif
    -                    s.state = DHCPS_STATE_ACK;
    -                } else {
    +                        s.state = DHCPS_STATE_ACK;
    +                    } else {
     #if DHCPS_DEBUG
    -                    DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\n");
    +                        DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\n");
     #endif
    -                    s.state = DHCPS_STATE_NAK;
    +                        s.state = DHCPS_STATE_NAK;
    +                    }
                     }
     
                     break;
    -
    -            case DHCP_OPTION_END: {
    -                is_dhcp_parse_end = true;
    -            }
    -            break;
    -        }
    -
    -        if (is_dhcp_parse_end) {
    -            break;
             }
     
    -        optptr += optptr[1] + 2;
    +        optptr += opt_len + 2;
         }
     
         switch (type) {
    
9f713dbc9498

fix(lwip): Fix DHCP servver OOB read issue

https://github.com/espressif/esp-idfDavid CermakApr 9, 2026via nvd-ref
1 file changed · +33 19
  • components/lwip/apps/dhcpserver/dhcpserver.c+33 19 modified
    @@ -1,5 +1,5 @@
     /*
    - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
    + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
      *
      * SPDX-License-Identifier: Apache-2.0
      */
    @@ -49,6 +49,7 @@
     #define DHCPNAK       6
     #define DHCPRELEASE   7
     
    +#define DHCP_OPTION_PAD           0
     #define DHCP_OPTION_SUBNET_MASK   1
     #define DHCP_OPTION_ROUTER        3
     #define DHCP_OPTION_DNS_SERVER    6
    @@ -879,7 +880,6 @@ static void send_ack(dhcps_t *dhcps, struct dhcps_msg *m, u16_t len)
     static u8_t parse_options(dhcps_t *dhcps, u8_t *optptr, s16_t len)
     {
         ip4_addr_t client;
    -    bool is_dhcp_parse_end = false;
         struct dhcps_state s;
     
         client.addr = *((uint32_t *) &dhcps->client_address);
    @@ -894,38 +894,52 @@ static u8_t parse_options(dhcps_t *dhcps, u8_t *optptr, s16_t len)
             DHCPS_LOG("dhcps: (s16_t)*optptr = %d\n", (s16_t)*optptr);
     #endif
     
    +        if (*optptr == DHCP_OPTION_PAD) {
    +            optptr++;
    +            continue;
    +        }
    +
    +        if (*optptr == DHCP_OPTION_END) {
    +            break;
    +        }
    +
    +        if (optptr + 1 >= end) {
    +            break;
    +        }
    +
    +        u8_t opt_len = optptr[1];
    +
    +        if (optptr + 2 + opt_len > end) {
    +            break;
    +        }
    +
             switch ((s16_t) *optptr) {
     
                 case DHCP_OPTION_MSG_TYPE:	//53
    -                type = *(optptr + 2);
    +                if (opt_len >= 1) {
    +                    type = optptr[2];
    +                }
                     break;
     
                 case DHCP_OPTION_REQ_IPADDR://50
    -                if (memcmp((char *) &client.addr, (char *) optptr + 2, 4) == 0) {
    +                if (opt_len >= 4) {
    +                    if (memcmp((char *) &client.addr, (char *) optptr + 2, 4) == 0) {
     #if DHCPS_DEBUG
    -                    DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n");
    +                        DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n");
     #endif
    -                    s.state = DHCPS_STATE_ACK;
    -                } else {
    +                        s.state = DHCPS_STATE_ACK;
    +                    } else {
     #if DHCPS_DEBUG
    -                    DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\n");
    +                        DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\n");
     #endif
    -                    s.state = DHCPS_STATE_NAK;
    +                        s.state = DHCPS_STATE_NAK;
    +                    }
                     }
     
                     break;
    -
    -            case DHCP_OPTION_END: {
    -                is_dhcp_parse_end = true;
    -            }
    -            break;
    -        }
    -
    -        if (is_dhcp_parse_end) {
    -            break;
             }
     
    -        optptr += optptr[1] + 2;
    +        optptr += opt_len + 2;
         }
     
         switch (type) {
    
d51b10760924

fix(lwip): Fix DHCP servver OOB read issue

https://github.com/espressif/esp-idfDavid CermakApr 9, 2026via nvd-ref
1 file changed · +33 19
  • components/lwip/apps/dhcpserver/dhcpserver.c+33 19 modified
    @@ -1,5 +1,5 @@
     /*
    - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
    + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
      *
      * SPDX-License-Identifier: Apache-2.0
      */
    @@ -49,6 +49,7 @@
     #define DHCPNAK       6
     #define DHCPRELEASE   7
     
    +#define DHCP_OPTION_PAD           0
     #define DHCP_OPTION_SUBNET_MASK   1
     #define DHCP_OPTION_ROUTER        3
     #define DHCP_OPTION_DNS_SERVER    6
    @@ -902,7 +903,6 @@ static void send_ack(dhcps_t *dhcps, struct dhcps_msg *m, u16_t len)
     static u8_t parse_options(dhcps_t *dhcps, u8_t *optptr, s16_t len)
     {
         ip4_addr_t client;
    -    bool is_dhcp_parse_end = false;
         struct dhcps_state s;
     
         client.addr = *((uint32_t *) &dhcps->client_address);
    @@ -917,38 +917,52 @@ static u8_t parse_options(dhcps_t *dhcps, u8_t *optptr, s16_t len)
             DHCPS_LOG("dhcps: (s16_t)*optptr = %d\n", (s16_t)*optptr);
     #endif
     
    +        if (*optptr == DHCP_OPTION_PAD) {
    +            optptr++;
    +            continue;
    +        }
    +
    +        if (*optptr == DHCP_OPTION_END) {
    +            break;
    +        }
    +
    +        if (optptr + 1 >= end) {
    +            break;
    +        }
    +
    +        u8_t opt_len = optptr[1];
    +
    +        if (optptr + 2 + opt_len > end) {
    +            break;
    +        }
    +
             switch ((s16_t) *optptr) {
     
                 case DHCP_OPTION_MSG_TYPE:	//53
    -                type = *(optptr + 2);
    +                if (opt_len >= 1) {
    +                    type = optptr[2];
    +                }
                     break;
     
                 case DHCP_OPTION_REQ_IPADDR://50
    -                if (memcmp((char *) &client.addr, (char *) optptr + 2, 4) == 0) {
    +                if (opt_len >= 4) {
    +                    if (memcmp((char *) &client.addr, (char *) optptr + 2, 4) == 0) {
     #if DHCPS_DEBUG
    -                    DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n");
    +                        DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n");
     #endif
    -                    s.state = DHCPS_STATE_ACK;
    -                } else {
    +                        s.state = DHCPS_STATE_ACK;
    +                    } else {
     #if DHCPS_DEBUG
    -                    DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\n");
    +                        DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\n");
     #endif
    -                    s.state = DHCPS_STATE_NAK;
    +                        s.state = DHCPS_STATE_NAK;
    +                    }
                     }
     
                     break;
    -
    -            case DHCP_OPTION_END: {
    -                is_dhcp_parse_end = true;
    -            }
    -            break;
    -        }
    -
    -        if (is_dhcp_parse_end) {
    -            break;
             }
     
    -        optptr += optptr[1] + 2;
    +        optptr += opt_len + 2;
         }
     
         switch (type) {
    

Vulnerability mechanics

Root cause

"The DHCP server option parser does not validate option lengths against the packet buffer, allowing out-of-bounds reads."

Attack vector

An attacker on the same Layer-2 network can send a crafted DHCP request to a device running the ESP-IDF DHCP server. This request exploits the parser's failure to validate option lengths, causing it to read past the end of the buffer into adjacent heap memory. This can lead to a denial of service by crashing the DHCP server task or corrupting its state, preventing address assignment to clients [ref_id=1].

Affected code

The vulnerability resides in the `parse_options()` function within `components/lwip/apps/dhcpserver/dhcpserver.c` [ref_id=1]. The function iterates through the BOOTP/DHCP options field without proper validation of option lengths against the received packet buffer.

What the fix does

The patch hardens the option parser by adding checks to validate option bounds before processing them. Specifically, it ensures that the option length byte and the declared payload length do not exceed the buffer boundaries. The parser now explicitly skips DHCP_OPTION_PAD, terminates on DHCP_OPTION_END, and checks that the option length is sufficient for the data it consumes, preventing out-of-bounds reads [ref_id=1]. The affected commits are [patch_id=5423955], [patch_id=5423956], [patch_id=5423957], [patch_id=5423958], [patch_id=5423959], and [patch_id=5423960].

Preconditions

  • configThe affected device must be configured to act as a DHCP server, typically via ESP-IDF's SoftAP functionality.
  • networkThe attacker must be on the same Layer-2 network as the vulnerable device.

Generated on Jun 10, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

7

News mentions

0

No linked articles in our index yet.