Audit report AR-53
Reported privately in an independent security review, 2026-09-27.
- Report date
- 2026-09-27
- Kind
- Bug
- Status on master
- Present
- Proposed issue state
- Open
Summary
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 operating system denies access to the socket. A user who is allowed to use HTTP RPC but not the node's Unix socket, for example another account sharing the data directory, gets an error suggesting the node is not running. The report is accurate. It is a compatibility problem in a new feature, not a stability bug, and -noipcconnect works around it. The behaviour change is right, but it fits better in bitcoin-cli than where the report puts it.
The report
connectAddress() already treats "no such file", "not a directory" and "connection refused" as "no IPC socket here" in auto mode and returns nothing, so the CLI uses HTTP. A "permission denied" error is passed on instead, and the CLI exits with "Probably bitcoin-node is not running". The node creates its socket readable only by its own account, while a shared data directory and -rpccookieperms=group can deliberately give another account HTTP RPC access, so that account hits this error on every call once the node also listens with -ipcbind=unix.
The report tested it by removing the socket's permissions for the same account: the default and explicit auto modes failed, -noipcconnect reached HTTP, and an explicit -ipcconnect=unix:<path> correctly reported the permission error. It did not test a real second account. It rates the problem low and asks for a decision before v32.0.
Proposed change
Add "permission denied" to the errors connectAddress() treats as "no socket" in auto mode:
- if (e.code() == std::errc::connection_refused || e.code() == std::errc::no_such_file_or_directory || e.code() == std::errc::not_a_directory) {
+ if (e.code() == std::errc::connection_refused || e.code() == std::errc::no_such_file_or_directory || e.code() == std::errc::not_a_directory || e.code() == std::errc::permission_denied) {
return nullptr;
A functional test in interface_ipc_cli.py removes the socket's permissions and checks both modes. The report considered handling the error in the CLI instead, and notes that on macOS a path that is not a socket may give a different error that this change does not cover.
Assessment
Accurate. The list of handled errors in src/ipc/interfaces.cpp is as described, and src/bitcoin-cli.cpp turns the exception into the "not running" hint. The node sets a private file mode mask at startup, so its socket is created accessible to its own account only. The auto default came in bitcoin#32297, merged for v32.
The fix belongs in bitcoin-cli. The interfaces::Ipc documentation says connectAddress() returns nothing when a connection was refused and throws on unexpected errors. Each error it handles today shows that nothing is listening. "Permission denied" shows the opposite: a node is listening, and this caller cannot reach it. Falling back to HTTP is the right answer for bitcoin-cli, but the auto mode is also meant for callers that start their own node when nothing is listening, such as a future bitcoin-gui, and for those "permission denied" is exactly the case where starting a second node on the same data directory is wrong. Handling permission_denied in the CLI's auto path, with a comment at connectAddress() saying why its list stays narrow, keeps that distinction. bitcoin-cli is the only caller today, so either place fixes the reported problem. The CLI change needs the same "was this auto mode?" flag as AR-52, so the two fit in one PR.
A warning on stderr when the CLI falls back for this reason was considered and is probably not wanted: the shared-directory setup is supported and would print it on every call.
Not counted as a stability bug in this survey: no crash, hang or leak.
Status
Present on master and in v32.0rc2. Next step: a Bitcoin Core PR together with AR-52. No public issue or PR yet.
Reported privately in an independent security review on 2026-09-27.