Cosmos · Report #3510161
Memory Exhaustion in CometBFT v1.0.1 via malicious ProposalMessage leads to network-wide denial of service
How it was found
Summary of Impact
CometBFT v1.0.1 contains a critical memory exhaustion vulnerability that allows any peer to crash nodes with a single ~50-byte P2P message. An attacker can send a malicious ProposalMessage with PartSetHeader.Total set to 2^32-1, causing the receiving node to immediately allocate 512 MB of memory without prior validation, resulting in an OOM kill.
The impact is complete network denial of service. For a 69-validator network (like Berachain mainnet), an attacker can halt consensus by crashing just 23 validators (34%) with only 1.15 KB of bandwidth.
Severity: HIGH/CRITICAL (depends on chain, if being validator is permissionless etc)
Steps to Reproduce
- Create a malicious
ProposalMessagewithPartSetHeader.Totalset to2^32-1(4,294,967,295) - Connect to a target node running CometBFT v1.0.1 via P2P protocol
- Send the malicious message to the target node
- The node will immediately allocate 512 MB of memory and be terminated by the OOM killer
Vulnerable code path:
- Entry point:
internal/consensus/reactor.go:334-336- No validation before processing - Unvalidated allocation:
internal/consensus/reactor.go:1169- Attacker controls Total value - Unsafe allocation:
internal/bits/bit_array.go:31- Unbounded memory allocation - Validation that never executes:
internal/consensus/state.go:2075-2077- Too late in execution flow
A second vulnerability vector exists in InitProposalBlockParts() at reactor.go:1184 which may be exploitable via NewValidBlockMessage or other message types.
Workarounds
No effective mitigation exists without a code patch. Operators must manually restart nodes after they crash.
Supporting Material/References
- Proof of Concept:
package main
import (
"math"
"github.com/cometbft/cometbft/types"
cmtcons "github.com/cometbft/cometbft/api/cometbft/consensus/v1"
)
func main() {
// Create malicious proposal
proposal := types.NewProposal(1, 0, -1, types.BlockID{
Hash: make([]byte, 32),
PartSetHeader: types.PartSetHeader{
Total: math.MaxUint32, // 2^32-1 = 4,294,967,295
Hash: make([]byte, 32),
},
}, nil)
proposal.Signature = []byte{0x01}
// Send to target node on port 26656
// (P2P connection and handshake code omitted for brevity)
// Result: Target node crashes within 10ms
}
- Affected networks include Berachain mainnet (69 validators) and potentially all blockchain networks using CometBFT v1.0.1
- Upstream v0.38.20 version correctly mitigates the issue