# Zebra Address Book Aborted by IPv4-Mapped Mempool Misbehavior Update

IPv4-mapped IPv6 address not canonicalized in Zebra's mempool misbehavior path trips an address-book assertion, letting any peer crash a synced node.

- Payout: Research
- Severity: high
- Program: Zebra
- Found by: Haxatron
- Disclosed: 2026-07-02
- CVE: CVE-2026-52829
- Write-up quality: 8/10
- Original: https://github.com/advisories/GHSA-63wg-wjjj-7cp8
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-63wg-wjjj-7cp8
- Tags: area:devices domain:network domain:oss impact:dos kind:research platform:ghsa sev:high tech:linux tech:rust technique:source-review vuln:dos

**Target:** P2P networking / address book (zebra-network, zebrad)
**Root cause:** Handshake path canonicalizes IPv4-mapped IPv6 peer addresses via MetaAddr::new_connected, but the mempool misbehavior path forwards the raw transient socket address through MetaAddrChange::UpdateMisbehavior without canonicalization. AddressBook::update then finds the canonical IPv4 entry and asserts previous.addr == change.addr, which fails.
**Steps:**
1. Run zebrad <= v4.4.1 on Linux with default `[::]` listen_addr (net.ipv6.bindv6only=0) and synced near tip.
2. Connect as a peer over IPv4 to the dual-stack listener; complete P2P handshake so the address book stores canonical `127.0.0.1:8233` while inbound inventory registration keeps transient `::ffff:127.0.0.1:8233`.
3. Advertise an invalid mempool transaction (e.g. a coinbase transaction) to trigger a misbehavior penalty.
4. Wait for the 30-second misbehavior batch flush; AddressBook::update applies UpdateMisbehavior with the raw IPv4-mapped address and the assertion `previous.addr == self.addr()` fails.
5. With `panic = "abort"` the process terminates; repeat after each restart for persistent downtime.
**How found:** Not stated in the advisory beyond the reporter's analysis of the divergence between the handshake canonicalization path and the mempool misbehavior path.
**Exploitation:** Remote unauthenticated peer completes a handshake over IPv4 to a dual-stack listener, sends one invalid mempool transaction advertisement, waits 30s for the misbehavior batch flush, and the node aborts. No mining, RPC, funds or privileges needed; repeatable after restart.
**Insight:** When a codebase canonicalizes addresses in one ingestion path (handshake) but passes raw socket addresses in another (misbehavior/inventory), look for equality assertions in the shared store that assume both paths agree — dual-stack IPv4-mapped IPv6 is the classic trigger.

