p2p: add validation check for initial self-announcement
What changed, and why it matters
This Bitcoin Core patch fixes a small inconsistency in how a node tells other nodes about its own network address. Normally, before sharing any address, the code checks whether the receiving peer can actually understand that address type. The very first self-announcement was skipping that check, which could cause a peer to receive an address format it does not support. The patch adds the missing compatibility check so the first announcement follows the same rule as all later ones.
Treat as a low-severity hardening fix. Backport to maintained branches if feasible, but no urgent security response is warranted absent evidence of exploitable consequences.
Security signals we found
Missing input/peer-capability validation in network message construction
Inconsistent enforcement of address-format compatibility
Potential protocol violation or peer confusion from unsupported address format
Fix aligns direct-send path with existing PushAddress() validation
Evidence from the diff
In PeerManagerImpl::MaybeSendAddr(), the initial self-announcement path constructed and pushed local_addr directly via MakeAndPushMessage(ADDRV2/ADDR) without calling IsAddrCompatible(). All other address pushes go through PushAddress(), which performs that check. The patch wraps the initial self-announcement in an IsAddrCompatible(peer, local_addr) guard, ensuring unsupported address formats are not sent to a peer.
Changed components
src/net_processing.cppPeerManagerImpl::MaybeSendAddr()ADDR / ADDRV2 P2P message generationInspect captured patch +7 / −5
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 1202eaf1..d7bfaed8 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -5521,11 +5521,13 @@ void PeerManagerImpl::MaybeSendAddr(CNode& node, Peer& peer, std::chrono::micros
// Send the initial self-announcement in its own message. This makes sure
// rate-limiting with limited start-tokens doesn't ignore it if the first
// message ends up containing multiple addresses.
- std::vector<CAddress> self_announcement {local_addr};
- if (peer.m_wants_addrv2) {
- MakeAndPushMessage(node, NetMsgType::ADDRV2, CAddress::V2_NETWORK(self_announcement));
- } else {
- MakeAndPushMessage(node, NetMsgType::ADDR, CAddress::V1_NETWORK(self_announcement));
+ if (IsAddrCompatible(peer, local_addr)) {
+ std::vector<CAddress> self_announcement{local_addr};
+ if (peer.m_wants_addrv2) {
+ MakeAndPushMessage(node, NetMsgType::ADDRV2, CAddress::V2_NETWORK(self_announcement));
+ } else {
+ MakeAndPushMessage(node, NetMsgType::ADDR, CAddress::V1_NETWORK(self_announcement));
+ }
}
} else {
// All later self-announcements are sent together with the other addresses.
Why this scored 37/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.