AI-generated analysisPublished automatically and not human-verified. Validated context appears in community notes below.
← Watch feed
High 76 Bitcoin

Merge bitcoin/bitcoin#36048: util: keep wallet names literal in notification commands

Public commit record

What the developer wrote

Authored by merge-script

96/100 · Strong
Merge bitcoin/bitcoin#36048: util: keep wallet names literal in notification commands

db39de5601094dc3f0b15ce4759e1b88025403c2 doc: add `-walletnotify` security note (Lőrinc)
1f9dfabef64121c5ea030f5dbaaaf2a6af706eef refactor: use string views in `ReplaceAll` (Lőrinc)
469b0e59a29ac48364c20268feeb4477b8ec9192 util: make `ReplaceAll` literal (Lőrinc)
604d7e8fdd95d22203120ca15d98d89f8668c240 test: characterize walletnotify shell injection (Lőrinc)
4efaa6763a7eb3614b78fa09e676fe0630c34678 test: simplify `ReplaceAll` coverage (Lőrinc)

Pull request description:

**Problem:** On non-Windows builds, operators can configure `-walletnotify` to run a command for wallet transactions, with `%w` replaced by the shell-escaped wallet name.
An authenticated RPC caller allowed to create wallets can supply a name containing `$'`, request an address, and send a transaction to it.
While replacing `%w`, `ReplaceAll()` passes the escaped wallet name to `std::regex_replace()` as replacement text.
There, `$'` copies the command suffix into the escaped name, breaking its quote accounting and allowing shell metacharacters in the wallet name to alter the command.
`runCommand()` passes the result to `system()`, so a suitable command template could execute additional shell commands as the node process account.
It is not reachable over P2P or by an unauthenticated network peer.
#25803 introduced this behavior in v24 when it replaced Boost's literal substitution with `std::regex_replace()`.

**Fix:** Restore the literal, non-recursive contract `ReplaceAll()` had before #25803, matching every current caller's literal search and replacement text, while the wallet notification test covers a wallet name containing `$'`.

**Related:** #35833 restricts control characters in new wallet names, while this change fixes replacement metacharacters in `ReplaceAll()`.

This was found and disclosed responsibly by the Red Team 🟥.

ACKs for top commit:
maflcko:
re-ACK db39de5601094dc3f0b15ce4759e1b88025403c2 💈
jeanpablojp:
re-ACK db39de5601094dc3f0b15ce4759e1b88025403c2
stickies-v:
re-ACK db39de5601094dc3f0b15ce4759e1b88025403c2

Tree-SHA512: 0be4adecfee50cb4dab90ae3386079767694a6b1fa1d7bd1f10ef73de88707b232f1ba4975a723c465a4d34d12296d501986c657d93bd8ae0bdced16afad1b5e
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference✓ Names security-relevant behavior explicitly
The short version

What changed, and why it matters

This commit fixes a shell command injection bug in Bitcoin Core's wallet notification feature. If a node operator had turned on -walletnotify on Linux or macOS, an attacker who could create wallets via RPC could craft a wallet name containing special characters. Due to a quirk in the previous string-replacement code, those characters could break out of the shell-escaped name and run extra commands as the Bitcoin node user. The fix replaces the regex-based string replacer with a simple literal one, and adds a test proving the attack no longer works.

Recommended action

Apply the patch and backport to supported releases that include the v24 regression (24.x, 25.x, 26.x, 27.x as applicable). Node operators using -walletnotify on non-Windows systems should upgrade promptly. Until patched, restrict RPC wallet-creation privileges to trusted callers and consider disabling -walletnotify if untrusted RPC access is possible.

Security signals we found

01

Command injection via -walletnotify placeholder expansion

02

std::regex_replace $' replacement metacharacter mishandling

03

Authenticated RPC-only attack surface (wallet creation)

04

Arbitrary command execution as node process account on non-Windows systems

05

Regression introduced in v24 by Boost-to-std::regex_replace migration

06

Responsible disclosure by external Red Team

Risk score

Why this scored 76/100

Our methodology →
Potential impact 25/30
Exploitability 18/25
Stealth signal 10/15
Affected reach 8/15
Confidence 10/10
Evidence quality 5/5
Human-validated context

Community notes

Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.

No validated notes yet.

The AI analysis stands alone for now. Submit a note if you can add evidence or important context.