Audit report AR-69
Reported privately in an independent security review, 2026-09-27.
- Report date
- 2026-09-27
- Kind
- API
- Status on master
- Present
- Proposed issue state
- Closed
Summary
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 encoder visits each element as const and cannot take ownership of it. The report is accurate for Bitcoin Core master and says itself that current libmultiprocess already fixed it, in mp#304. It is a compile error, not a runtime failure, and no Bitcoin Core interface on master returns such a list, so it is an API finding with no bug page.
The report
BuildList() turns a C++ container into a Cap'n Proto list and loops over it with for (const auto& elem : value). For a List(Interface) result backed by std::vector<std::unique_ptr<Interface>>, sending each element means calling unique_ptr::release() to hand the object to the IPC server, which cannot be done on a const element, so the generated code fails to compile.
The report rates it low. Bitcoin Core's current IPC interfaces have no such result, so nothing fails in a running node or wallet; a developer adding one gets a compile error. No remote trigger or funds effect.
Proposed change
Loop with an explicit iterator and pass each element through unchanged, moving it out only when the container itself is a temporary:
- for (const auto& elem : value) {
- BuildField(TypeList<LocalType>(), invoke_context, ListOutput<typename decltype(list)::Builds>(list, i), elem);
- ++i;
+ for (auto it = value.begin(); it != value.end(); ++it, ++i) {
+ if constexpr (std::is_lvalue_reference_v<Value&&>) {
+ BuildField(TypeList<LocalType>(), invoke_context, ListOutput<typename decltype(list)::Builds>(list, i), *it);
+ } else {
+ BuildField(TypeList<LocalType>(), invoke_context, ListOutput<typename decltype(list)::Builds>(list, i), std::move(*it));
+ }
}
A test interface method returning a list of owned objects compiles and round-trips with the fix. The report says a public Bitcoin Core change should come from a normal update of the library.
Assessment
Accurate, and already fixed upstream. Bitcoin Core master's copy still has the const loop. mp#304 (merged 2026-08-14) replaced it with an explicit iterator and added the same kind of test; it explains that the const loop came in with mp#277 and broke returning external signers in bitcoin#10102, which is not merged. Bitcoin Core's copy of the library was last updated on 2026-07-14, before the fix.
No Bitcoin Core interface on master returns a list of interfaces; its lists hold only data and integers. A compile error cannot affect a running program, so this is not a stability bug.
Status
Fixed in libmultiprocess master by mp#304; present in Bitcoin Core master until its libmultiprocess copy is updated. Nothing further needed in libmultiprocess.
Reported privately in an independent security review on 2026-09-27.