Audit report AR-10

Reported privately in an independent security review, 2026-08-07.

Report date
2026-08-07
Kind
Hardening
Status on master
Present
Proposed issue state
Open

Summary

libmultiprocess reads C++ enum values off the wire with a plain static_cast, without checking that the integer matches a declared enumerator. Code that switches over the enum can then see a value no local caller could produce. The report is accurate about the code. A well-behaved peer never sends such a value, and for most enum types the cast itself is well defined, so this is hardening.

The report

The enum codec in include/mp/type-number.h does:

static_cast<LocalType>(input.get())

without checking whether the value corresponds to a declared enumerator. Downstream exhaustive switch statements and invariants may then receive states that are impossible in local C++ calls. The report lists invalid enum values among its suggested regression tests and gives no reproduction.

Proposed change

Run a generated or customizable validity check before constructing the enum value. No code.

Assessment

The code is unchanged on libmultiprocess master: return read_dest.construct(static_cast<LocalType>(input.get()));, with a comment explaining a suppressed clang-tidy out-of-range warning for enums without a zero value.

What an out-of-range value does depends on the enum:

Bitcoin Core's schemas carry C++ enums as integer fields, not as Cap'n Proto enums. The static_assert on enum size in BuildPrimitive, added by mp#120, guards the build side only. A peer built by the same code never sends an unlisted value. A peer built from a newer schema could send a newer enumerator, which is a compatibility question worth deciding explicitly: reject it, or map it to a default. A peer sending arbitrary values on purpose already has unauthenticated RPC access under Bitcoin Core's trust model.

Related input-validation report: AR-27 (malformed JSON accepted as null, since fixed). A protocol fuzz target (AR-06) would exercise this path.

Status

Present on master. Next step, if wanted: an opt-in customization point in libmultiprocess (for example a validity-check overload that applications can define for an enum) that lets the reader throw on unknown values. Idea; no issue open.

Reported privately in an independent security review on 2026-08-07.