Audit report AR-78
Reported privately in an independent security review, 2026-10-10.
- Report date
- 2026-10-10
- Kind
- Hardening
- Status on master
- Present
- Proposed issue state
- Open
Summary
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 listens on a shorter path than the one configured. The report is accurate, apart from naming libmultiprocess where the code is in Bitcoin Core. It only involves the operator's own startup configuration and cannot crash or stall anything, so it is input-validation hardening, not a stability bug. It came with a change merged on 2026-10-08 and is in no release.
The report
Since -ipcbind gained per-address socket options, Unix socket paths are URL-decoded so a path can contain an encoded comma (%2C). The decoder also turns %00 into a NUL byte. The parser accepts the decoded path, but the address is later copied into the socket address structure with strncpy, which stops at the NUL. For example, -ipcbind=unix:path%00suffix is validated as path, NUL, suffix, but the node binds path. The same happens when socket options follow the address.
The report rates it low. The input is local startup configuration that no peer, RPC caller or IPC client can change. The listener could appear at a different filesystem name than the configuration states, which could collide with another local socket or confuse tools that check the configured path. No process failure or data effect was shown.
Proposed change
Decode the address through one helper that rejects an embedded NUL, for addresses with and without socket options:
+util::Result<std::string> DecodeAddress(std::string_view encoded)
+{
+ std::string decoded{UrlDecode(encoded)};
+ if (decoded.find('\0') != std::string::npos) {
+ return util::Error{Untranslated("Unix socket address must not contain NUL bytes")};
+ }
+ return decoded;
+}
Two new cases in the address parsing test check the error, and the existing %2C cases still pass.
Assessment
Accurate. On Bitcoin Core master, parseListenAddress() URL-decodes Unix addresses, and the decoder turns any valid %XX, including %00, into a byte. The truncation happens in Bitcoin Core's own src/ipc/process.cpp, not in libmultiprocess: it builds the full path, checks its length, and copies it with strncpy, which stops at the NUL. Before binding, the same code removes any existing socket file at the shortened path, so a collision would replace that other socket rather than fail. That is still something only the operator's configuration can cause.
The decoding was added in bitcoin#35037 (merged 2026-10-08). Before that, -ipcbind values were not decoded, and a command-line argument cannot contain a NUL byte, so no release is affected. The copy is bounded and the buffer is cleared first, so there is no memory error. The fix is correct and small. Rejecting a NUL where the path is copied would cover every caller, but only -ipcbind is decoded today.
Status
Present on master, in no release. Low priority; no public issue or PR yet.
Reported privately in an independent security review on 2026-10-10.