RPC API crash affecting programs with greater than or equal to 25% of the market capitalization on top of the respective layer
Unintended chain split (network partition)
Increasing network processing node resource consumption by at least 30% without brute force actions, compared to the preceding 24 hours
Description
Brief/Intro
base-consensus accepts an unlimited number of inbound libp2p connections because connection_limits::Behaviour is never added to the Swarm and the CLI parameters peers_hi / peers_lo are emitted as metrics only — never wired to the swarm. An attacker can establish thousands of permanent authenticated connections from a single IP, exhausting the process file descriptor limit (EMFILE) on production systems, isolating the node from the gossip network, and crashing its RPC.
libp2p::connection_limits::Behaviour is absent. Without it, libp2p 0.56 enforces zero connection limits — the Swarm accepts every inbound TCP connection until OS resources are exhausted.
The CLI flags --p2p.peers.hi (default 30) and --p2p.peers.lo (default 20) are parsed by base/crates/client/cli/src/p2p.rs but only written to Prometheus metrics in base/bin/consensus/src/metrics.rs. They never appear in NetworkConfig, NetworkBuilder, or GossipDriverBuilder. The configured limit of 30 peers has zero effect.
Additionally, the production binary never raises the file descriptor soft limit:
On a standard Linux system, ulimit -n defaults to 1024. With ~27 FDs used at baseline, ~997 attacker connections exhaust the pool.
Each attacker connection completes the full Noise XX handshake + Yamux muxer negotiation, making it a permanent established connection. The idle_connection_timeout=60s is bypassed because Yamux keeps open substreams that prevent the idle detection from firing (confirmed libp2p issue #5190, still open in libp2p 0.56).
Impact Details
Production nodes running with the default OS file descriptor limit (ulimit -n 1024) have their FD pool exhausted by ~997 attacker connections, causing the gossip mesh to collapse and the RPC to freeze — any dApp or service relying on that node loses access to current chain state. Even on nodes with raised FD limits, the attack causes +30% memory and +318% CPU increase from a single IP with zero ongoing cost.
create the attack.py file and paste the following script:
2
Start the devnet:
3
Wait for all containers to be healthy:
4
Take baseline measurement:
5
Run the attack (in a separate terminal):
6
Observe the impact:
All connections from a single IP. Zero failures. Zero authentication beyond a fresh random keypair. Connections are permanent — they survive indefinitely with zero attacker maintenance after the initial 50-second setup.
Remediation
Rate limits in p2p node mechanism is crucial to avoid this type of attack where further exploitation can lead to more damage.