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, where $' copies the command suffix into the escaped name and allows its shell metacharacters 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 🟥.