Audit report AR-09
Reported privately in an independent security review, 2026-08-07.
- Report date
- 2026-08-07
- Kind
- Hardening
- Status on master
- Fixed in bitcoin#35037
- Proposed issue state
- Closed
- Linked bugs
- Bug 78: Listener at its connection limit stops accepting after a local disconnect
Summary
Until 2026-10-08, Bitcoin Core's -ipcbind listeners accepted any number of simultaneous connections. libmultiprocess has supported an optional per-listener limit since mp#269, but Bitcoin Core did not pass one. The report is accurate and rates this as defense in depth itself. Any process that can reach the socket already has unauthenticated RPC access, so a cap is hardening; the Bitcoin Core side is now fixed by bitcoin#35037.
The report
ListenConnections accepts an optional maximum number of active connections, and the default is unlimited. Bitcoin Core's CapnpProtocol::listen calls it without a maximum. A local process that can reach the Unix socket can therefore open connections until it runs the node out of file descriptors, and each connection also holds a Connection object, RPC state and cleanup work.
The report calls this lower severity because Bitcoin Core normally places the socket inside the protected data directory, and a process running as the same user already has many ways to deny service. It recommends a configured cap as defense in depth, and lists connection-count exhaustion among its suggested regression tests. It gives no reproduction.
Proposed change
Add default listener limits and per-connection resource limits. No code.
Assessment
Accurate. On libmultiprocess master the signature is ListenConnections(EventLoop& loop, SocketId fd, InitImpl& init, std::optional<size_t> max_connections = std::nullopt), and Bitcoin Core's src/ipc/capnp/protocol.cpp calls mp::ListenConnections<messages::Init>(*m_loop, listen_fd, init) with no limit.
This is a resource-limit gap, not a stability bug: reaching it takes a client opening many connections on purpose. -ipcbind is off by default, and its help text in src/init.cpp says that enabling it "gives local processes that can access the socket unauthenticated RPC access", which includes stop.
bitcoin#35037 added a per-address max-connections= option to -ipcbind and reserves file descriptors for IPC connections; bitcoin#34978, a separate reservation PR, was closed. The library's limit logic has its own open bug, which the survey suggested fixing before a default limit was turned on: a listener at its max-connection limit never accepts again after the server closes one of its connections locally, with a fix in mp#361.
AR-19 reports the same gap independently, with more detail and a patch. Related limits: AR-04 (threads), AR-07 (per-method quotas), AR-21 (stopping a listener), AR-22 (unresolved calls), AR-23 (block templates).
Status
Fixed on master by bitcoin#35037 (merged 2026-10-08 as 442884f5f3b): each -ipcbind address takes a max-connections= limit (default 16, at most 256 in total), protocol.cpp passes it to ListenConnections, and startup counts the IPC listeners and connection slots in the node's file descriptor budget. It landed before the mp#361 fix for the listener that stops accepting at its limit, but that bug still cannot be triggered on master: Bitcoin Core closes connections locally only at shutdown.
Reported privately in an independent security review on 2026-08-07.