Audit report AR-77

Reported privately in an independent security review, 2026-10-01.

Report date
2026-10-01
Kind
Bug
Status on master
Present
Proposed issue state
Open

Summary

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 serving. The report is accurate and its one-line fix is right. Nothing in Bitcoin Core is affected today: the only code that spawns a bitcoin-node child is a test-only RPC, and no fatal node error can happen in that child. A wrong exit code is not a stability bug, so this has no bug page.

The report

startSpawnedProcess() sets its output status to failure, serves the parent's IPC connection, and sets the status to success when serving ends. Fatal node errors store EXIT_FAILURE in the node's own exit status, but MakeNodeInit() never copies that value back, so the process exits successfully.

The report includes a unit test that runs the real parent and child IPC path: the child records a failure while serving, the parent disconnects, and the child exits with status 0. The report rates it low and asks for a fix before the next release, describing it as a regression in the IPC process path new in v32. A parent process, service supervisor or test harness could take a failed node for a clean exit. It needs local process spawning and a separate fatal error; no network trigger or data effect was shown.

Proposed change

After serving ends, return the node's recorded exit status instead of a fixed success value:

     if (init->m_ipc->startSpawnedProcess(argc, argv, exit_status)) {
+        exit_status = node.exit_status.load();
         return nullptr;
     }

The report considered having startSpawnedProcess() return the status directly, and rejected it as a wider interface change with no benefit for this caller.

Assessment

Accurate about the code. On Bitcoin Core master, startSpawnedProcess() sets EXIT_SUCCESS after serving unconditionally, and MakeNodeInit() does not look at the node's status. The fix is correct and changes nothing for a child that has no failure.

Two details differ:

The node does not crash, hang or leak, so this is a correctness issue rather than a stability bug. The test is heavier than the fix needs: it forks inside the unit test binary and builds bitcoin-node.cpp into the IPC test library.

Status

Present on master. Low priority; no public issue or PR yet.

Reported privately in an independent security review on 2026-10-01.