SIGN IN SIGN UP

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
M
merge-script committed
b811aeabad94ef48cd0f0fb1d2fcc456594aeedb