From 39958d2e18832ada5d329c756ead2bd6be662f23 Mon Sep 17 00:00:00 2001 From: lodekeeper Date: Thu, 26 Mar 2026 21:26:47 +0000 Subject: [PATCH 1/3] fix: set finite gossipsub decode limits for control messages js-gossipsub defaults all protobuf decode limits (maxSubscriptions, maxMessages, maxIwantMessageIDs, etc.) to Infinity. This means an attacker can craft gossipsub RPCs with arbitrarily large control message arrays that are fully decoded into memory before any application-level caps apply. Set finite decode limits as defense-in-depth against resource exhaustion via crafted control messages. Values are generous enough for normal Ethereum CL gossipsub operation while preventing abuse. Context: Lighthouse v8.1.3 patched analogous unbounded IWANT/IDONTWANT vulnerabilities in rust-libp2p (CVEs pending disclosure). --- .../beacon-node/src/network/gossip/gossipsub.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/beacon-node/src/network/gossip/gossipsub.ts b/packages/beacon-node/src/network/gossip/gossipsub.ts index f5d5b0a22683..63bcb7a4381b 100644 --- a/packages/beacon-node/src/network/gossip/gossipsub.ts +++ b/packages/beacon-node/src/network/gossip/gossipsub.ts @@ -179,6 +179,19 @@ export class Eth2Gossipsub { // This should be large enough to not send IDONTWANT for "small" messages // See https://github.com/ChainSafe/lodestar/pull/7077#issuecomment-2383679472 idontwantMinDataSize: 16829, + // Protobuf decode limits to bound memory allocation from untrusted RPC messages. + // js-gossipsub defaults all limits to Infinity. Setting finite values provides + // defense-in-depth against resource exhaustion via crafted control messages. + // See: Lighthouse v8.1.3 security patches for analogous rust-libp2p fixes. + decodeRpcLimits: { + maxSubscriptions: 512, + maxMessages: 256, + maxIhaveMessageIDs: 200, + maxIwantMessageIDs: 200, + maxIdontwantMessageIDs: 2000, + maxControlMessages: 500, + maxPeerInfos: 100, + }, })(modules.libp2p.services.components) as GossipSubInternal; if (metrics) { From 7a02bc2d29a7b62489a02a567cb3bbc7b7db666c Mon Sep 17 00:00:00 2001 From: lodekeeper Date: Thu, 26 Mar 2026 21:37:43 +0000 Subject: [PATCH 2/3] fix: raise IHAVE/IWANT decode limits to match GossipsubMaxIHaveLength maxIhaveMessageIDs and maxIwantMessageIDs at 200 would truncate honest peers that send up to GossipsubMaxIHaveLength (5000) message IDs per heartbeat. Raise both to 5000 to align decode-time bounds with the runtime protocol constant. --- packages/beacon-node/src/network/gossip/gossipsub.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/beacon-node/src/network/gossip/gossipsub.ts b/packages/beacon-node/src/network/gossip/gossipsub.ts index 63bcb7a4381b..1513ec1c09d7 100644 --- a/packages/beacon-node/src/network/gossip/gossipsub.ts +++ b/packages/beacon-node/src/network/gossip/gossipsub.ts @@ -186,8 +186,8 @@ export class Eth2Gossipsub { decodeRpcLimits: { maxSubscriptions: 512, maxMessages: 256, - maxIhaveMessageIDs: 200, - maxIwantMessageIDs: 200, + maxIhaveMessageIDs: 5000, + maxIwantMessageIDs: 5000, maxIdontwantMessageIDs: 2000, maxControlMessages: 500, maxPeerInfos: 100, From 5d43ede52786b56d99091c852fb8f460f27bffbf Mon Sep 17 00:00:00 2001 From: lodekeeper Date: Fri, 27 Mar 2026 11:49:15 +0000 Subject: [PATCH 3/3] fix: tighten gossipsub decode limit bounds --- .../beacon-node/src/network/gossip/gossipsub.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/beacon-node/src/network/gossip/gossipsub.ts b/packages/beacon-node/src/network/gossip/gossipsub.ts index 1513ec1c09d7..b132bd977d74 100644 --- a/packages/beacon-node/src/network/gossip/gossipsub.ts +++ b/packages/beacon-node/src/network/gossip/gossipsub.ts @@ -182,15 +182,20 @@ export class Eth2Gossipsub { // Protobuf decode limits to bound memory allocation from untrusted RPC messages. // js-gossipsub defaults all limits to Infinity. Setting finite values provides // defense-in-depth against resource exhaustion via crafted control messages. + // NOTE: maxIhaveMessageIDs / maxIwantMessageIDs are upstream field names but + // they actually bound the number of outer ControlIHave / ControlIWant entries, + // not nested messageIDs inside each entry. + // NOTE: maxMessages must stay high enough for current js-libp2p behavior: + // handleIWant() may serialize many RPC.Message entries into a single response RPC. // See: Lighthouse v8.1.3 security patches for analogous rust-libp2p fixes. decodeRpcLimits: { maxSubscriptions: 512, - maxMessages: 256, - maxIhaveMessageIDs: 5000, - maxIwantMessageIDs: 5000, - maxIdontwantMessageIDs: 2000, - maxControlMessages: 500, - maxPeerInfos: 100, + maxMessages: 5000, + maxIhaveMessageIDs: 256, + maxIwantMessageIDs: 16, + maxIdontwantMessageIDs: 16, + maxControlMessages: 256, + maxPeerInfos: 32, }, })(modules.libp2p.services.components) as GossipSubInternal;