Audit reports

These are the 79 reports from independent security reviews of the IPC code done in 2026. The reviewers reported them privately, and they are published here with their permission. Most are hardening suggestions, API and design observations, or possible bugs rather than confirmed failures, and they have not all been reproduced. Each page gives the report's content (the problem, its impact, the proposed change and any reproduction hints) followed by what the survey found about it: whether the problem is real, whether it is already fixed or tracked, and its status on master today. Some reports describe a bug that also has its own page in the bug list, because it was found independently or reported at about the same time; those pages link to each other.

ReportSummaryDateKindStatus on masterProposed issueBugs
AR-01A server that closes a new connection right away can make the connecting client free its Connection object before the ProxyClient that should own it exists, a...2026-08-07BugFixedClosedBug 72
AR-02When an interface method takes another interface by C++ reference (Impl&), libmultiprocess passes it to the peer as a capability backed by a shared_ptr with a...2026-08-07DesignPresentOpen
AR-03If an interface method returned a std::span of bytes, or had one as an output parameter, the generated client would hand back a view into the Cap'n Proto...2026-08-07APIPresentOpenBug 23
AR-04Any IPC peer holding a ThreadMap capability can ask the other process to create operating-system threads without limit, through makeThread or through makePool...2026-08-07HardeningPresentOpen
AR-05The report mentions the thread-context cleanup races described in mp#189 but does not count them, on the grounds that later event-loop changes may have fixed...2026-08-07BugPartly fixedOpenBug 37, Bug 45
AR-06The report says libmultiprocess has no fuzz target for its protocol or codecs, and that its sanitizer CI runs only ThreadSanitizer, with no AddressSanitizer...2026-08-07TestPresentOpen
AR-07The only bound on what an incoming IPC message can contain is Cap'n Proto's default traversal limit (64 MiB of message data, nesting depth 64). libmultiprocess...2026-08-07DesignPresentOpen
AR-08On macOS, a client that disconnects while still queued for accept() makes Cap'n Proto's accepted-socket setup throw EINVAL, and the IPC listener stops...2026-08-07BugFixedClosedBug 80
AR-09Until 2026-10-08, Bitcoin Core's -ipcbind listeners accepted any number of simultaneous connections. libmultiprocess has supported an optional per-listener...2026-08-07HardeningFixedClosedBug 78
AR-10libmultiprocess reads C++ enum values off the wire with a plain static_cast, without checking that the integer matches a declared enumerator. Code that...2026-08-07HardeningPresentOpen
AR-11When a client reads a struct, tuple, optional, vector or map result into an existing output object, libmultiprocess updates it one field or element at a time...2026-08-07DesignPresentOpen
AR-12A collection of error-handling weaknesses in libmultiprocess's process helpers: descriptor leaks on some setup failures, no EINTR retry around waitpid...2026-08-07HardeningPartly fixedOpenBug 2
AR-13ReadDestUpdate::construct destroys the caller's output object before constructing its replacement in the same storage. If the replacement's constructor throws...2026-08-07HardeningPresentOpen
AR-14If anything throws while an IPC client is building a request, the event loop logs and discards the exception, no request is sent, and the calling thread waits...2026-08-07BugPresentOpenBug 86, Bug 63
AR-15SpawnProcess can leak file descriptors into child processes in several ways: a socket without the close-on-exec flag (libmultiprocess v13.0), a short window...2026-08-07BugPartly fixedOpenBug 87, Bug 69
AR-16If the implicit construct() call made while creating an IPC client fails, the ProxyClient is never fully constructed, so its destructor never frees the...2026-08-07BugFixedClosedBug 73
AR-17For interfaces that define a destroy method (Bitcoin Core's BlockTemplate and Echo), destroy resets the server's implementation pointer without a lock, while...2026-08-13BugPresentOpenBug 81, Bug 82
AR-18The depends build decides whether to regenerate its archive of the local libmultiprocess source by comparing file modification times, so an existing archive...2026-08-16BuildPresentOpen
AR-19Until 2026-10-08, Bitcoin Core's -ipcbind listeners accepted any number of simultaneous connections: libmultiprocess has an optional per-listener limit, but...2026-08-16HardeningFixedClosedBug 78
AR-20RPC calls made over IPC carry a username chosen by the client, and Bitcoin Core applies that user's -rpcwhitelist settings to the call. The report first...2026-08-16DocsNot applicableOpen
AR-21libmultiprocess's ListenConnections() returns nothing, so an application cannot stop accepting on one listening socket without tearing down the whole event...2026-08-16APIPresentOpenBug 78
AR-22A libmultiprocess server admits any number of unresolved calls on one connection, with no limit on their count or on the size of their parameters. A client...2026-08-16HardeningPresentOpen
AR-23A mining client can keep requesting block templates over IPC and hold on to every one of them, because bitcoin-node has no limit on the number of live...2026-08-16HardeningPresentOpenBug 55
AR-24The Mining interface's checkBlock() and submitBlock() pass the caller's CBlock to validation with its cached check flags intact, so an in-process C++ caller...2026-08-20APIPresentOpenBug 53
AR-25IpcImpl in Bitcoin Core declares its protocol member before its process member, so C++ destroys the process object first, although protocol cleanup (the...2026-08-20DesignPresentOpen
AR-26BlockTemplate::submitSolution returns false early when no coinbase is given, without touching its reason and debug output strings, so an in-process caller that...2026-08-26APIPresentOpen
AR-27Bitcoin Core's IPC code sends UniValue values as JSON text and ignored the result of parsing it on arrival, so malformed JSON from a client reached the...2026-08-26HardeningFixedClosed
AR-28The Mining interface's transaction lookups by txid and wtxid promise one nullable result per requested id, but return an empty list when the node has no...2026-08-31APIPresentOpen
AR-29The regtest-only -blockversion option is read as a 64-bit integer and then narrowed into the block header's 32-bit version, so an out-of-range value becomes a...2026-09-03BugPresentOpen
AR-30When bitcoin-node binds an IPC Unix socket, it first removes any existing socket at that path, even one that a running process is still listening on. A second...2026-09-03DesignPresentOpen
AR-31BlockTemplate::submitSolution rewrites the stored block (coinbase, header fields, merkle root and cached flags) without a lock, while the template's getters...2026-09-06BugPresentOpenBug 83
AR-32On an abrupt client disconnect, a server worker thread's first getResults() call could read Cap'n Proto connection state while the event loop was tearing that...2026-09-07BugFixedClosedBug 79
AR-33libmultiprocess's deprecated EventLoop constructor, which accepts the old-style log callback, always wraps that callback in a new LogFn, even when it is empty....2026-09-16BugPresentOpen
AR-34SetThread() in libmultiprocess reserves an empty entry in a connection's thread map, releases the lock, and then calls the factory that creates the thread...2026-09-16BugPresentOpenBug 86
AR-35Several libmultiprocess lifecycle paths log before doing essential cleanup, and some log from destructors that cannot throw. If an application's log callback...2026-09-16HardeningPresentOpenBug 8
AR-36With tests enabled, Bitcoin Core's cmake/libmultiprocess.cmake sets properties on the libmultiprocess mptest target unconditionally, but the bundled...2026-09-18BuildPresentOpen
AR-37On Windows, a stale Unix-domain socket file left behind by an unclean exit would not be removed on the next start, because Microsoft's std::filesystem does not...2026-09-18BugNot applicableClosed
AR-38Mining.waitTipChanged takes a Float64 timeout from the IPC client and checks it with Assume(timeout >= 0ms) before clamping it. A negative timeout aborts...2026-09-18BugPresentOpenBug 84
AR-39The getblocktemplate RPC help for the fee field of each entry in transactions still explains what the value means "for coinbase transactions", but that array...2026-09-18DocsPresentOpen
AR-40A comment on BlockCreateOptions::coinbase_output_script in src/node/mining_types.h still refers to coinbase_max_additional_weight, a field that was renamed to...2026-09-19DocsPresentOpen
AR-41doc/multiprocess.md tells readers to set HOST_PLATFORM from gcc -dumpmachine or clang -dumpmachine, but depends names its output directory from...2026-09-20DocsPresentOpen
AR-42A mining client that calls Mining.checkBlock while the node is starting on an empty data directory or reindexing, after the mining interface is available but...2026-09-26BugPresentOpenBug 94
AR-43When bitcoin-node shuts down, an IPC call that is already running on a worker thread can keep using the chain manager, mempool or block template state after...2026-09-26BugPresentOpenBug 44
AR-44Mining.interrupt() and BlockTemplate.interruptWait() are meant to cancel a client's long waits, but each stores the request in a single flag that the first...2026-09-27BugPresentOpenBug 99
AR-45While SpawnProcess prepares a child process, both ends of the new IPC socket pair can be inherited by any other program the host process starts at the same...2026-09-27BugPresentOpenBug 69
AR-46If ThreadMap.makePool fails partway through creating a pool of worker threads, the client gets an error, but the threads created so far stay installed as the...2026-09-27BugPresentOpen
AR-47When libmultiprocess creates a worker thread for a client (makeThread or makePool), there is a short step between starting the thread and handing it to the...2026-09-27BugPresentOpen
AR-48If bitcoind or bitcoin-node fails to start while an IPC mining client is waiting in makeMining for the node to load, the node logs "Shutdown done" and then...2026-09-27BugPresentOpenBug 96
AR-49This report describes the same two problems as AR-17: calling a method on an object after the client destroyed it makes the server call through a null pointer...2026-09-27BugPresentClosedBug 81, Bug 82
AR-50Bitcoin Core creates its IPC event loop on a background thread, and an exception while creating it escapes that thread and aborts the whole process instead of...2026-09-27BugPresentOpenBug 98
AR-51If two threads in one Bitcoin Core process make their first IPC call at the same time, both can try to start the IPC event loop thread, and the second attempt...2026-09-27BugPresentOpenBug 95
AR-52Starting with v32, bitcoin-cli tries the node's IPC socket before HTTP by default (-ipcconnect=auto). If the socket belongs to an older v30 or v31...2026-09-27BugPresentOpen
AR-53With the default -ipcconnect=auto in v32, bitcoin-cli falls back to HTTP when the node's IPC socket is missing or refuses connections, but not when the...2026-09-27BugPresentOpen
AR-54Several steps of Bitcoin Core's IPC setup leave resources behind when they fail. If starting the IPC event loop fails after a socket has been opened, the...2026-09-27BugPresentOpenBug 97
AR-55An RPC reply larger than about 64 MiB fails when bitcoin-cli uses IPC, while the same call works over HTTP. The cause is Cap'n Proto's default per-message...2026-09-27DesignPresentOpen
AR-56When -rpcwhitelist stops a user from calling a method, the RPC server reports it only as HTTP status 403 with an empty body. The new IPC path in bitcoin-cli...2026-09-27BugPresentOpen
AR-57The report finds two problems in how libmultiprocess sets up IPC sockets. First, if allocating Cap'n Proto's wrapper object for a socket fails, nothing owns...2026-09-27BugPresentOpenBug 101
AR-58If anything throws while an IPC client prepares a request, the event loop logs and discards the exception, no request is sent, and the calling thread waits...2026-09-27BugPresentOpenBug 86
AR-59When a server method finishes on its worker thread, libmultiprocess hands the result back by running a short function on the event loop that resolves the...2026-09-27HardeningPresentOpen
AR-60Before libmultiprocess runs an asynchronous IPC method on a worker thread, it installs a callback that protects the request if the client cancels or...2026-09-27HardeningPresentOpen
AR-61When a libmultiprocess server runs a call on a worker thread, it keeps a reference to that thread's server object until the call is finished, and releases it...2026-09-27HardeningPresentOpen
AR-62When a client releases a libmultiprocess server object without calling destroy, the server's destructor hands the object to a background cleanup thread. That...2026-09-27BugPresentOpenBug 100
AR-63When a libmultiprocess server object is released without its client calling destroy, the object's cleanup callbacks run on the asynchronous cleanup thread with...2026-09-27HardeningPresentOpen
AR-64Two mining interface methods, getTransactionsByTxID and getTransactionsByWitnessID, return one serialized transaction for every id in the request, with no...2026-09-27HardeningPresentOpen
AR-65When Bitcoin Core reads a serialized value, such as a transaction id or a transaction, from an IPC Data field, it decodes one value and ignores any bytes left...2026-09-27HardeningPresentOpen
AR-66libmultiprocess's WaitProcess gives up if a signal interrupts its waitpid call (EINTR), although the right response is to call it again. The report describes...2026-09-27BugPresentOpenBug 91
AR-67In Bitcoin Core's copy of libmultiprocess, SpawnProcess reports success even when the child process fails to start its program, so the caller sees only a...2026-09-27HardeningPresentClosed
AR-68Two lifetime bugs in how a libmultiprocess client is created, both in Bitcoin Core's copy of the library: if the server disconnects while the client is being...2026-09-27BugPresentClosedBug 72, Bug 73
AR-69In Bitcoin Core's copy of libmultiprocess, an IPC method that returns a list of interface objects owned by std::unique_ptr does not compile, because the list...2026-09-27APIPresentClosed
AR-70In Bitcoin Core's copy of libmultiprocess, the parent's end of the socket that SpawnProcess creates for a child process is never marked close-on-exec, so any...2026-09-28BugPresentClosedBug 69
AR-71When an IPC request is handed to a worker thread, libmultiprocess chains it behind a "thread ready" signal, and the code that fires the next signal lives...2026-09-28BugPresentOpen
AR-72When libmultiprocess spawns a child process, the child closes inherited file descriptors only below the current soft descriptor limit. A descriptor opened...2026-09-28BugPresentOpenBug 87
AR-73A thread's Waiter holds one pending call, and the gate that keeps a thread proxy from posting a second call before the first starts only covers that one proxy....2026-09-28BugPresentOpenBug 102
AR-74ThreadMap.makePool(count) creates as many operating-system threads as the client asks for, up to about four billion, one at a time on the event loop thread....2026-09-28HardeningPresentOpen
AR-75When a Connection is destroyed, it runs a list of synchronous cleanup callbacks with no exception handling, so if one throws, the rest are skipped and the...2026-09-29HardeningPresentOpen
AR-76If a thread that made IPC calls exits at the moment its connection is destroyed on the event loop thread, both sides can tear down the same thread proxy and...2026-09-29BugPresentOpenBug 37
AR-77When bitcoin-node runs as a child process spawned over IPC, it exits with status 0 once its parent disconnects, even if a fatal error was recorded while it was...2026-10-01BugPresentOpen
AR-78An encoded NUL byte (%00) in an -ipcbind Unix socket path is decoded and accepted, but the path handed to the operating system stops at the NUL, so the node...2026-10-10HardeningPresentOpen
AR-79If an IPC listener's accept() fails once, even with a temporary error such as running out of file descriptors (EMFILE), libmultiprocess stops listening for...2026-10-15BugPresentOpenBug 88