From 01a3303ae99c788c0e8f93da59280425620a04f8 Mon Sep 17 00:00:00 2001 From: Shantanu Date: Sat, 15 Aug 2026 17:46:05 +0530 Subject: [PATCH] fix(p2p): harden hello payload validation against malformed payloads and DoS --- main.py | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/main.py b/main.py index b37fce4..5062652 100644 --- a/main.py +++ b/main.py @@ -193,10 +193,28 @@ async def handler(data): payload = data.get("data") peer_addr = data.get("_peer_addr", "unknown") - if payload is None and msg_type in ("hello", "chain_request", "chain_response"): - return + if payload is None and msg_type in ("chain_request", "chain_response"): + return None + + if msg_type in ("chain_request", "chain_response") and not isinstance(payload, dict): + logger.warning( + "Malformed %s from %s: payload is not a dict (got %s).", + msg_type, peer_addr, type(payload).__name__ + ) + return None + + # Note: a null payload in a hello message deliberately falls through + # to the isinstance(payload, dict) guard below, which disconnects the peer. if msg_type == "hello": + if not isinstance(payload, dict): + logger.warning( + "Malformed hello from %s: payload is not a dict (got %s). Disconnecting.", + peer_addr, type(payload).__name__ + ) + asyncio.create_task(network.disconnect_peer(peer_addr)) + return ValidationStatus.MALFORMED + peer_chain_id = payload.get("chain_id") peer_gen_hash = payload.get("genesis_hash") if peer_chain_id != chain.chain_id: @@ -208,8 +226,18 @@ async def handler(data): asyncio.create_task(network.disconnect_peer(peer_addr)) return - logger.info("🔄 Handshake successful with %s", peer_addr) peer_tip = payload.get("latest_block_index", 0) + + if not isinstance(peer_tip, int) or isinstance(peer_tip, bool) or peer_tip < 0: + invalid_val = peer_tip if isinstance(peer_tip, int) and not isinstance(peer_tip, bool) else type(peer_tip).__name__ + logger.warning( + "Malformed hello from %s: latest_block_index is not a valid integer (got %s). Disconnecting.", + peer_addr, invalid_val + ) + asyncio.create_task(network.disconnect_peer(peer_addr)) + return ValidationStatus.MALFORMED + + logger.info("🔄 Handshake successful with %s", peer_addr) if peer_tip > chain.last_block.index: logger.info("📡 Peer %s is ahead (%d > %d). Initiating chunked sync...", peer_addr, peer_tip, chain.last_block.index) request_chain(network, chain.last_block.index + 1, 500)