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.
| Report | Summary | Date | Kind | Status on master | Proposed issue | Bugs |
|---|---|---|---|---|---|---|
| AR-01 | A 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-07 | Bug | Fixed | Closed | Bug 72 |
| AR-02 | When 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-07 | Design | Present | Open | |
| AR-03 | If 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-07 | API | Present | Open | Bug 23 |
| AR-04 | Any 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-07 | Hardening | Present | Open | |
| AR-05 | The 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-07 | Bug | Partly fixed | Open | Bug 37, Bug 45 |
| AR-06 | The 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-07 | Test | Present | Open | |
| AR-07 | The 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-07 | Design | Present | Open | |
| AR-08 | On 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-07 | Bug | Fixed | Closed | Bug 80 |
| AR-09 | Until 2026-10-08, Bitcoin Core's -ipcbind listeners accepted any number of simultaneous connections. libmultiprocess has supported an optional per-listener... | 2026-08-07 | Hardening | Fixed | Closed | Bug 78 |
| AR-10 | libmultiprocess 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-07 | Hardening | Present | Open | |
| AR-11 | When 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-07 | Design | Present | Open | |
| AR-12 | A collection of error-handling weaknesses in libmultiprocess's process helpers: descriptor leaks on some setup failures, no EINTR retry around waitpid... | 2026-08-07 | Hardening | Partly fixed | Open | Bug 2 |
| AR-13 | ReadDestUpdate::construct destroys the caller's output object before constructing its replacement in the same storage. If the replacement's constructor throws... | 2026-08-07 | Hardening | Present | Open | |
| AR-14 | If 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-07 | Bug | Present | Open | Bug 86, Bug 63 |
| AR-15 | SpawnProcess 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-07 | Bug | Partly fixed | Open | Bug 87, Bug 69 |
| AR-16 | If 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-07 | Bug | Fixed | Closed | Bug 73 |
| AR-17 | For 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-13 | Bug | Present | Open | Bug 81, Bug 82 |
| AR-18 | The depends build decides whether to regenerate its archive of the local libmultiprocess source by comparing file modification times, so an existing archive... | 2026-08-16 | Build | Present | Open | |
| AR-19 | Until 2026-10-08, Bitcoin Core's -ipcbind listeners accepted any number of simultaneous connections: libmultiprocess has an optional per-listener limit, but... | 2026-08-16 | Hardening | Fixed | Closed | Bug 78 |
| AR-20 | RPC 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-16 | Docs | Not applicable | Open | |
| AR-21 | libmultiprocess's ListenConnections() returns nothing, so an application cannot stop accepting on one listening socket without tearing down the whole event... | 2026-08-16 | API | Present | Open | Bug 78 |
| AR-22 | A 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-16 | Hardening | Present | Open | |
| AR-23 | A 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-16 | Hardening | Present | Open | Bug 55 |
| AR-24 | The 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-20 | API | Present | Open | Bug 53 |
| AR-25 | IpcImpl in Bitcoin Core declares its protocol member before its process member, so C++ destroys the process object first, although protocol cleanup (the... | 2026-08-20 | Design | Present | Open | |
| AR-26 | BlockTemplate::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-26 | API | Present | Open | |
| AR-27 | Bitcoin 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-26 | Hardening | Fixed | Closed | |
| AR-28 | The 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-31 | API | Present | Open | |
| AR-29 | The 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-03 | Bug | Present | Open | |
| AR-30 | When 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-03 | Design | Present | Open | |
| AR-31 | BlockTemplate::submitSolution rewrites the stored block (coinbase, header fields, merkle root and cached flags) without a lock, while the template's getters... | 2026-09-06 | Bug | Present | Open | Bug 83 |
| AR-32 | On 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-07 | Bug | Fixed | Closed | Bug 79 |
| AR-33 | libmultiprocess'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-16 | Bug | Present | Open | |
| AR-34 | SetThread() 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-16 | Bug | Present | Open | Bug 86 |
| AR-35 | Several libmultiprocess lifecycle paths log before doing essential cleanup, and some log from destructors that cannot throw. If an application's log callback... | 2026-09-16 | Hardening | Present | Open | Bug 8 |
| AR-36 | With tests enabled, Bitcoin Core's cmake/libmultiprocess.cmake sets properties on the libmultiprocess mptest target unconditionally, but the bundled... | 2026-09-18 | Build | Present | Open | |
| AR-37 | On 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-18 | Bug | Not applicable | Closed | |
| AR-38 | Mining.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-18 | Bug | Present | Open | Bug 84 |
| AR-39 | The 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-18 | Docs | Present | Open | |
| AR-40 | A 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-19 | Docs | Present | Open | |
| AR-41 | doc/multiprocess.md tells readers to set HOST_PLATFORM from gcc -dumpmachine or clang -dumpmachine, but depends names its output directory from... | 2026-09-20 | Docs | Present | Open | |
| AR-42 | A 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-26 | Bug | Present | Open | Bug 94 |
| AR-43 | When 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-26 | Bug | Present | Open | Bug 44 |
| AR-44 | Mining.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-27 | Bug | Present | Open | Bug 99 |
| AR-45 | While 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-27 | Bug | Present | Open | Bug 69 |
| AR-46 | If 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-27 | Bug | Present | Open | |
| AR-47 | When 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-27 | Bug | Present | Open | |
| AR-48 | If 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-27 | Bug | Present | Open | Bug 96 |
| AR-49 | This 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-27 | Bug | Present | Closed | Bug 81, Bug 82 |
| AR-50 | Bitcoin 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-27 | Bug | Present | Open | Bug 98 |
| AR-51 | If 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-27 | Bug | Present | Open | Bug 95 |
| AR-52 | Starting 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-27 | Bug | Present | Open | |
| AR-53 | With 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-27 | Bug | Present | Open | |
| AR-54 | Several 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-27 | Bug | Present | Open | Bug 97 |
| AR-55 | An 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-27 | Design | Present | Open | |
| AR-56 | When -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-27 | Bug | Present | Open | |
| AR-57 | The 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-27 | Bug | Present | Open | Bug 101 |
| AR-58 | If 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-27 | Bug | Present | Open | Bug 86 |
| AR-59 | When 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-27 | Hardening | Present | Open | |
| AR-60 | Before 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-27 | Hardening | Present | Open | |
| AR-61 | When 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-27 | Hardening | Present | Open | |
| AR-62 | When 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-27 | Bug | Present | Open | Bug 100 |
| AR-63 | When 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-27 | Hardening | Present | Open | |
| AR-64 | Two mining interface methods, getTransactionsByTxID and getTransactionsByWitnessID, return one serialized transaction for every id in the request, with no... | 2026-09-27 | Hardening | Present | Open | |
| AR-65 | When 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-27 | Hardening | Present | Open | |
| AR-66 | libmultiprocess'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-27 | Bug | Present | Open | Bug 91 |
| AR-67 | In 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-27 | Hardening | Present | Closed | |
| AR-68 | Two 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-27 | Bug | Present | Closed | Bug 72, Bug 73 |
| AR-69 | In 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-27 | API | Present | Closed | |
| AR-70 | In 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-28 | Bug | Present | Closed | Bug 69 |
| AR-71 | When 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-28 | Bug | Present | Open | |
| AR-72 | When libmultiprocess spawns a child process, the child closes inherited file descriptors only below the current soft descriptor limit. A descriptor opened... | 2026-09-28 | Bug | Present | Open | Bug 87 |
| AR-73 | A 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-28 | Bug | Present | Open | Bug 102 |
| AR-74 | ThreadMap.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-28 | Hardening | Present | Open | |
| AR-75 | When 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-29 | Hardening | Present | Open | |
| AR-76 | If 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-29 | Bug | Present | Open | Bug 37 |
| AR-77 | When 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-01 | Bug | Present | Open | |
| AR-78 | An 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-10 | Hardening | Present | Open | |
| AR-79 | If 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-15 | Bug | Present | Open | Bug 88 |
No reports match these filters.