CVE-2026-19577: Out-of-Bounds Read in Zephyr RTOS IPv6 Routing
Executive Summary
CVE-2026-19577 is a high-severity out-of-bounds (OOB) read vulnerability affecting Zephyr RTOS IPv6 routing subsystem. An attacker on the local network link can trigger a kernel panic in debug builds or leak up to 8 bytes of static RAM in production environments. The vulnerability requires adjacent network access but no authentication or special configuration.
CVSS v3.1 Score: 7.1 (High)
Attack Vector: Adjacent Network (Layer 2)
Primary Impact: Denial of Service & Memory Disclosure
What Is CVE-2026-19577?
Vulnerability Overview
CVE-2026-19577 resides in the net_route_ipv6_packet() function within Zephyr RTOS’s IPv6 routing subsystem (subsys/net/ip/route_ipv6.c). The vulnerability occurs when the code attempts to retrieve a link-layer address for an unresolved IPv6 neighbor cache entry without proper validation.
The core issue: when a neighbor cache entry remains in an INCOMPLETE state (unresolved), the code assigns an invalid index value (NET_NBR_LLADDR_UNKNOWN = 0xFF). Subsequent calls to net_nbr_get_lladdr() calculate a pointer approximately 2.5 KB beyond the valid array boundary. Because this pointer is non-NULL, downstream NULL checks fail to catch the error.
Two distinct impacts emerge:
- Debug builds (
CONFIG_ASSERT=y): Kernel assertion fires immediately, causing system panic - Production builds (assertions disabled): Leaked memory bytes are embedded in outgoing network frames
Affected Systems and Versions
| Component | Details |
|---|---|
| Product | Zephyr Real-Time Operating System (RTOS) |
| Subsystem | Network Stack / IPv6 Routing |
| Affected Versions | All versions with vulnerable code pattern in route_ipv6.c and nbr.c when CONFIG_NET_IPV6_ROUTE is enabled |
| Default Status | Enabled by default when IPv6 neighbor caching is active |
Why This Matters for Your Deployment
Zephyr RTOS powers embedded IoT devices, industrial controllers, and edge computing platforms. This vulnerability affects:
- Default configurations: No special routing setup required—vulnerability exists in standard builds
- Wide attack surface: Any device on the same local network can exploit this
- Silent data leakage: Production systems leak memory without obvious indicators
- Service disruption: Debug builds crash repeatedly under attack
Organizations deploying Zephyr-based devices in shared network environments face immediate risk.
How the Vulnerability Works
Root Cause in the Code
The vulnerability stems from a missing validation check in the IPv6 routing path:
// Vulnerable code flow in net_route_ipv6_packet()
struct net_nbr *nbr = net_route_ipv6_get_info(...);
// No check for nbr->idx == NET_NBR_LLADDR_UNKNOWN (0xFF)
struct net_linkaddr *lladdr = net_nbr_get_lladdr(nbr->idx);
// This NULL check passes because pointer is non-NULL (but out-of-bounds)
if (lladdr == NULL) {
return -EINVAL; // Never reached
}
// Proceeds with invalid memory reference
memcpy(dest_addr, lladdr->addr, lladdr->len);
The net_nbr_get_lladdr() function in subsys/net/ip/nbr.c performs a simple array offset calculation without bounds validation:
// Inside net_nbr_get_lladdr()
return &net_neighbor_lladdr[idx]; // No bounds check on idx
When idx = 255 (0xFF), this returns a pointer far beyond the allocated array.
Memory Layout and Out-of-Bounds Access
Assuming default configuration (CONFIG_NET_IPV6_MAX_NEIGHBORS = 8):
Memory Layout:
┌─────────────────────────────────────────────────────────────┐
│ net_neighbor_lladdr[0..7] │ Unrelated Static RAM │ [OOB] │
│ (Valid: 64 bytes) │ (~2.5 KB) │ Access│
└─────────────────────────────────────────────────────────────┘
↑ ↑
Valid array Index 255 pointer
(indices 0-7) (~2.5 KB past end)
The calculation: &net_neighbor_lladdr[255] produces a valid pointer address pointing to unallocated memory containing adjacent static data structures.
Why NULL Checks Fail
Standard NULL pointer validation cannot catch this error because:
- Pointer is non-NULL: The calculated address is a valid memory location (just not intended for this array)
- No runtime bounds checking: The function lacks index range validation
- Macro-only protection:
NET_ASSERTmacros are disabled in production builds - Assumption of validity: Downstream code assumes any non-NULL pointer is safe
Attack Scenarios You Need to Know
Scenario A: Denial of Service (Assert-Enabled Builds)
Prerequisites:
- Target compiled with
CONFIG_ASSERT=y(common in development/debug builds) - Attacker has Layer 2 access to target’s network segment
Attack Steps:
- Create unresolved neighbor entry: Send IPv6 Router Advertisement (RA) lacking Source Link-Layer Address option, or trigger Neighbor Solicitation to non-existent address
- Trigger routing: Send unicast IPv6 packet destined for the unresolved neighbor
- Kernel panic:
net_route_ipv6_packet()callsnet_nbr_get_lladdr(0xFF), assertion fires, system crashes
Impact: Repeatable remote denial of service—attacker can crash device repeatedly with minimal packet overhead
Real-world scenario: Industrial IoT device on shared factory network receives malicious IPv6 packets, crashes repeatedly, disrupting production monitoring
Scenario B: Memory Disclosure (Production Builds)
Prerequisites:
- Target compiled with assertions disabled (typical production configuration)
- Attacker has Layer 2 access
- Passive network listener present (or attacker captures own traffic)
Attack Steps:
- Create unresolved neighbor entry: Same method as Scenario A
- Send trigger packet: Unicast IPv6 packet to unresolved neighbor
- Memory leak: Code reads from
&net_neighbor_lladdr[255], interprets adjacent static RAM as validstruct net_linkaddr - Exfiltration: If the
lenfield at that memory location passes validation, up to 8 bytes are copied into outgoing Ethernet frame’s destination address - Broadcast: Frame transmitted on local network, exposing leaked data to any L2 listener
Impact: Incremental memory disclosure—attacker learns 8 bytes per malicious packet, can target specific memory regions through repeated attacks
Real-world scenario: Attacker on corporate network segment leaks cryptographic keys, session tokens, or configuration data from embedded device’s static RAM
Attack Prerequisites and Feasibility
| Requirement | Feasibility | Notes |
|---|---|---|
| Layer 2 access | High | Must be on same network segment; no Internet routing required |
| Authentication | None | Unauthenticated attack |
| Special config | None | Works on default builds |
| Packet crafting | Low | Standard IPv6 Neighbor Discovery messages |
| Detection difficulty | High | Appears as normal IPv6 traffic |
Exploitability Rating: HIGH
No specialized tools or deep networking knowledge required. Standard IPv6 utilities can craft necessary packets.
Severity and Risk Assessment
CVSS v3.1 Score Breakdown
CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:H
| Metric | Value | Justification |
|---|---|---|
| Attack Vector (AV) | Adjacent (A) | Requires Layer 2 network access; no Internet routing |
| Attack Complexity (AC) | Low (L) | No special conditions; default configurations vulnerable |
| Privileges Required (PR) | None (N) | Unauthenticated attack |
| User Interaction (UI) | None (N) | No user action needed |
| Scope (S) | Unchanged (U) | Impact limited to vulnerable system |
| Confidentiality (C) | Low (L) | Max 8 bytes leaked per packet; limited data exposure |
| Integrity (I) | None (N) | Read-only vulnerability; no data modification |
| Availability (A) | High (H) | System panic in debug builds; DoS possible |
Base Score: 7.1 (HIGH)
Threat Actor Profile
- Skill Level: Low to Medium
- Access Requirements: Local network presence
- Motivation: Service disruption, data exfiltration, reconnaissance
- Typical Actors: Disgruntled employees, network-adjacent attackers, supply chain adversaries
What This Vulnerability Cannot Do
Important limitations to understand:
- ❌ No Remote Code Execution: Read-only access at fixed offset; no pointer manipulation
- ❌ No Out-of-Bounds Write: Cannot modify memory or inject code
- ❌ No Internet-based exploitation: Requires Layer 2 adjacency
- ❌ No privilege escalation: Operates within existing process context
- ❌ No controllable data leak: Attacker cannot choose which bytes are leaked
- ❌ No authentication bypass: Unrelated to access control systems
Detecting Active Exploitation
Network-Based Detection Indicators
Monitor for these IPv6 traffic patterns:
1. Router Advertisements (ICMPv6 Type 134) lacking Source Link-Layer Address option
- Unusual RA frequency from single source
- RAs with router lifetime but no link-layer info
2. Neighbor Solicitations (ICMPv6 Type 135) to non-existent addresses
- NS queries for addresses never seen in ARP/NDP before
- Rapid NS bursts followed by unicast traffic to same targets
3. Unicast IPv6 packets to unresolved neighbors
- Traffic to addresses in "incomplete" state
- Packets arriving immediately after NS without ND reply
Detection rule example (Suricata/Snort):
alert ipv6 any any -> any any (msg:"CVE-2026-19577 Exploitation Attempt";
icmpv6_type:134; content:"|3a|"; distance:0; within:1;
sid:1000001; rev:1;)
Static Code Analysis Patterns
Search your codebase for vulnerable patterns:
# Find unchecked net_nbr_get_lladdr() calls
grep -n "net_nbr_get_lladdr" subsys/net/ip/*.c | grep -v "NET_NBR_LLADDR_UNKNOWN"
# Identify missing bounds checks
grep -B5 "net_nbr_get_lladdr" subsys/net/ip/route_ipv6.c | grep -v "if.*idx"
Vulnerable code signature:
// Pattern 1: Direct call without validation
struct net_linkaddr *lladdr = net_nbr_get_lladdr(nbr->idx);
// Pattern 2: NULL check only (insufficient)
if (lladdr != NULL) {
// Process lladdr
}
// Pattern 3: Missing INCOMPLETE check
if (nbr->state == NET_NBR_REACHABLE) {
// Still vulnerable if idx not checked
}
Log Signals to Monitor
System logs to watch:
- Kernel assertion failures in
net_nbr.corroute_ipv6.c - Unexpected system reboots correlated with IPv6 traffic spikes
- Memory access violations in network stack
- Repeated kernel panics from same source IP
Application logs:
- Network interface errors or resets
- IPv6 routing failures
- Neighbor cache state anomalies
Fixing the Vulnerability
Code-Level Remediation
Primary fix in subsys/net/ip/route_ipv6.c:
// BEFORE (Vulnerable)
static int net_route_ipv6_packet(struct net_pkt *pkt, ...)
{
struct net_nbr *nbr = net_route_ipv6_get_info(...);
struct net_linkaddr *lladdr = net_nbr_get_lladdr(nbr->idx);
if (lladdr == NULL) {
return -EINVAL;
}
// ... proceed with lladdr
}
// AFTER (Fixed)
static int net_route_ipv6_packet(struct net_pkt *pkt, ...)
{
struct net_nbr *nbr = net_route_ipv6_get_info(...);
// Explicit check for unresolved neighbor
if (nbr->idx == NET_NBR_LLADDR_UNKNOWN) {
NET_DBG("Neighbor unresolved, cannot route");
return -EINVAL;
}
struct net_linkaddr *lladdr = net_nbr_get_lladdr(nbr->idx);
if (lladdr == NULL) {
return -EINVAL;
}
// ... proceed with lladdr
}
Secondary fix in subsys/net/ip/nbr.c:
// BEFORE (Vulnerable)
struct net_linkaddr *net_nbr_get_lladdr(uint8_t idx)
{
return &net_neighbor_lladdr[idx];
}
// AFTER (Fixed with bounds checking)
struct net_linkaddr *net_nbr_get_lladdr(uint8_t idx)
{
if (idx == NET_NBR_LLADDR_UNKNOWN ||
idx >= CONFIG_NET_IPV6_MAX_NEIGHBORS) {
return NULL;
}
return &net_neighbor_lladdr[idx];
}
Patching Strategy
Immediate actions:
- Identify affected devices: Audit all Zephyr deployments with IPv6 enabled
- Prioritize by exposure: Focus on devices with Layer 2 network access
- Prepare patches: Apply fixes to your Zephyr fork or wait for official release
- Test thoroughly: Validate IPv6 routing functionality after patching
Phased rollout:
Phase 1 (Week 1): Patch development/test environments
Phase 2 (Week 2): Patch staging/pre-production systems
Phase 3 (Week 3-4): Staged production rollout by region/criticality
Phase 4 (Ongoing): Monitor for exploitation attempts
Testing Your Fix
Validation checklist:
# 1. Compile with fix applied
west build -b <board> -d build_fixed
# 2. Unit test: Verify bounds checking
# Add test case for idx == 0xFF
test_net_nbr_get_lladdr_invalid_index()
# 3. Integration test: IPv6 routing with unresolved neighbors
# Send RA without link-layer option, verify graceful handling
# Send unicast to unresolved neighbor, verify packet drop (not crash)
# 4. Regression test: Normal IPv6 routing still works
# Verify standard neighbor resolution and routing functions
# Test with resolved neighbors, verify no performance impact
# 5. Stress test: Rapid neighbor state changes
# Simulate high-frequency ND messages
# Verify no memory leaks or crashes
Test code example:
void test_cve_2026_19577_fix(void)
{
// Create unresolved neighbor entry
struct net_nbr *nbr = net_nbr_get_unused();
nbr->idx = NET_NBR_LLADDR_UNKNOWN;
// Attempt to get link-layer address
struct net_linkaddr *lladdr = net_nbr_get_lladdr(nbr->idx);
// Verify fix: should return NULL, not out-of-bounds pointer
zassert_is_null(lladdr, "Expected NULL for invalid index");
}
Immediate Workarounds
Network Defense Measures
While awaiting patches, implement these controls:
1. IPv6 Router Advertisement Guard (RA Guard)
Deploy on managed switches to block untrusted RAs:
[Cisco IOS Example]
ipv6 nd raguard policy STRICT
device-role host
router-preference ignore
ra-guard enable
!
interface GigabitEthernet0/1
ipv6 nd raguard attach-policy STRICT
Effect: Prevents attacker from creating unresolved neighbor entries via spoofed RAs
2. VLAN Segmentation
Isolate Zephyr devices on dedicated VLANs:
[Network Design]
- IoT Devices VLAN: 100 (isolated)
- Management VLAN: 200 (restricted access)
- Production VLAN: 300 (no untrusted devices)
Access Control:
- Block inter-VLAN IPv6 traffic except where necessary
- Monitor VLAN 100 for suspicious ND activity
Effect: Limits attacker’s ability to reach vulnerable devices
3. Private VLAN (PVLAN) Implementation
[Cisco Catalyst Example]
vlan 100
private-vlan community
vlan 101
private-vlan isolated
vlan 102
private-vlan primary
private-vlan association 100,101
interface GigabitEthernet0/1
switchport private-vlan host-association 102 100
Effect: Prevents device-to-device communication on same segment
Configuration Hardening
Disable IPv6 routing if not required:
// In prj.conf
CONFIG_NET_IPV6_ROUTE=n
Restrict neighbor cache size:
// In prj.conf
CONFIG_NET_IPV6_MAX_NEIGHBORS=4 # Reduce from default 8
Enable IPv6 address filtering:
// In application code
// Only accept packets from known IPv6 addresses
struct in6_addr allowed_peers[] = {
// List of trusted IPv6 addresses
};
Disable IPv6 if not needed:
// In prj.conf
CONFIG_NET_IPV6=n
CONFIG_NET_IPV4=y # Use IPv4 only if feasible
Temporary Mitigation While Patching
Short-term protective measures:
| Mitigation | Effectiveness | Complexity |
|---|---|---|
| RA Guard | High | Medium |
| VLAN isolation | High | Medium |
| Network monitoring | Medium | Low |
| Disable IPv6 | Very High | Low |
| Reduce neighbor cache | Medium | Low |
Recommended interim approach:
- Immediate (Day 1): Enable RA Guard on network switches
- Short-term (Week 1): Implement VLAN segmentation
- Medium-term (Week 2): Deploy network monitoring for ND anomalies
- Long-term (Week 3+): Apply code patches and redeploy
FAQ
Can this vulnerability be exploited over the Internet?
No. CVE-2026-19577 requires adjacent network access (Layer 2). The attacker must be able to send raw IPv6 Neighbor Discovery messages directly to the target device on the same network segment. Internet-based exploitation is not possible because:
- IPv6 ND messages don’t traverse routers
- Requires direct Ethernet/link-layer frame transmission
- No DNS or application-layer attack vector exists
Implication: Devices on isolated networks or behind properly configured firewalls have reduced risk, but internal network threats remain significant.
Does this enable remote code execution?
No. This is strictly a read-only vulnerability. The out-of-bounds access is limited to reading memory at a fixed offset (index 255). There is:
- No out-of-bounds write capability
- No pointer manipulation or corruption
- No stack overflow or heap spray
- No direct path to arbitrary code execution
However: In theory, if leaked memory contains function pointers or other sensitive data, an attacker could potentially chain this with other vulnerabilities. Treat as part of a multi-stage attack, not a standalone RCE.
Why do NULL pointer checks not catch this?
The vulnerability bypasses NULL checks because net_nbr_get_lladdr() returns a valid, non-NULL pointer—just one pointing to unintended memory:
// Index 255 calculation:
&net_neighbor_lladdr[255] // Valid address, wrong location
// ~2.5 KB past array end
// Points to adjacent static RAM
// NULL check passes:
if (lladdr == NULL) { // FALSE - pointer is not NULL
return -EINVAL; // Never executed
}
Why this matters: Standard defensive programming (NULL checks) is insufficient. Bounds validation is required.
Do I need special routing configuration to be vulnerable?
No. CONFIG_NET_IPV6_ROUTE is enabled by default whenever IPv6 neighbor caching is active in Zephyr RTOS. Most standard networking builds are vulnerable without any special setup:
// Default Zephyr configuration
CONFIG_NET_IPV6=y // Enabled by default
CONFIG_NET_IPV6_NBR_CACHE=y // Enabled by default
CONFIG_NET_IPV6_ROUTE=y // Enabled by default
Implication: You’re likely vulnerable unless you explicitly disabled IPv6 routing in your build configuration.
What’s the difference between debug and production impact?
| Build Type | Configuration | Impact | Severity |
|---|---|---|---|
| Debug | CONFIG_ASSERT=y |
Kernel panic on trigger | Critical (DoS) |
| Production | CONFIG_ASSERT=n |
Memory leak (8 bytes/packet) | High (data exposure) |
Debug builds: Crash immediately when vulnerability triggered—obvious but disruptive
Production builds: Silent memory leakage—harder to detect but enables data exfiltration
Recommendation: Even production builds should be patched; don’t rely on assertions being disabled for security.
How much data can be leaked?
Maximum 8 bytes per malicious packet. The leak is constrained by:
- Fixed offset: Always reads from index 255 (~2.5 KB past array)
- Structure size:
struct net_linkaddrcontains 8-byte address field - Length validation: Code checks
len <= NET_LINK_ADDR_MAX_LENGTH(typically 6-8 bytes) - Single read: One packet = one leak operation
Cumulative risk: Attacker can send multiple packets to leak different memory regions incrementally. Over time, significant data exposure is possible.
Example: 100 packets = 800 bytes of leaked memory
Can I disable IPv6 routing to avoid this?
Yes, but with caveats. You can disable IPv6 routing:
// In prj.conf
CONFIG_NET_IPV6_ROUTE=n
However:
- This disables routing functionality—may break legitimate use cases
- Other IPv6 vulnerabilities may still exist
- Not a permanent solution; patching is still required
- Reduces functionality unnecessarily
Better approach: Apply the code patch rather than disabling features.
What Zephyr versions are affected?
All versions with the vulnerable code pattern in route_ipv6.c and nbr.c where CONFIG_NET_IPV6_ROUTE is enabled alongside the IPv6 neighbor cache.
Specific affected versions:
- Zephyr 2.7.x through 3.x (confirmed)
- Likely earlier versions (2.6.x and prior)
- Any custom Zephyr fork with IPv6 networking
Check your version:
west --version
# or
cat VERSION
Recommendation: Assume your version is affected unless explicitly patched. Check Zephyr security advisories for official patch releases.
References
Official Sources
- CVE Identifier: CVE-2026-19577
- Zephyr Project: https://www.zephyrproject.org/
- Zephyr Security: https://docs.zephyrproject.org/latest/security/
Affected Code Files
subsys/net/ip/route_ipv6.c— IPv6 routing logicsubsys/net/ip/nbr.c— Neighbor cache managementsubsys/net/ip/ipv6.c— IPv6 packet processing
Related Standards
- RFC 4861 — Neighbor Discovery for IPv6
- RFC 4862 — IPv6 Stateless Address Autoconfiguration
- RFC 6775 — IPv6 Neighbor Discovery Extensions for Low-Power and Lossy Networks
Detection Tools
- Wireshark: IPv6 protocol analysis and ND packet inspection
- tcpdump: Capture suspicious IPv6 traffic patterns
- Suricata/Snort: Network-based intrusion detection
Key Takeaways
✅ Immediate Actions:
- Audit all Zephyr deployments for IPv6 enablement
- Implement RA Guard on network switches
- Segment IoT devices into isolated VLANs
- Monitor for suspicious IPv6 Neighbor Discovery traffic
✅ Short-term (1-2 weeks):
- Apply code patches to development builds
- Test thoroughly in staging environments
- Deploy network monitoring for exploitation attempts
✅ Long-term (2-4 weeks):
- Roll out patched firmware to production devices
- Maintain network segmentation and monitoring
- Subscribe to Zephyr security advisories
Remember: This vulnerability requires local network access but no authentication. Treat it seriously in any environment where untrusted devices share network segments with your Zephyr deployments.
