#36142 net: validate Tor onion service replies and cached keys

full analysis

https://github.com/bitcoin/bitcoin/pull/36142 · l0rinc · +106/-17 in 2 files, 3 commits · labels: P2P, Needs rebase

Goal

  • Prevent Tor command and argument injection from malicious or impersonated Tor control daemons
  • Stop attackers from hijacking inbound onion connections or triggering Tor shutdowns

Validates Tor v3 service IDs and private keys received from the Tor control daemon and cached on disk. The private key format is strictly checked against the expected 64-byte Ed25519-V3 base64 payload both when received and before reuse from disk, and invalid service IDs are rejected before advertising.

Problem: Tor reply parsing unescapes quoted strings, allowing a malicious or impersonated Tor control endpoint to return a private key containing spaces or CRLF line breaks. When bitcoind reuses the cached key in an unquoted ADD_ONION command upon restart, these characters cause command injection (such as triggering Tor shutdowns) or argument injection (such as adding duplicate Port bindings that hijack inbound onion traffic).

Category: P2P (#2 of 65)

P2 · bug fix

  • P2 because it fixes an injection flaw in Tor control that can hijack inbound onion connections
  • Injected arguments in cached keys could divert incoming connections to an attacker target
  • Protects node connectivity and transaction privacy for onion service operators

P2 because it fixes an injection vulnerability in the Tor control integration that could hijack inbound onion connections. As demonstrated during review, an injected `Port=` argument in a cached key causes Tor to route half of incoming onion connections away from the node to an attacker-controlled target, compromising node connectivity and transaction privacy.

Membership: Modifies src/torcontrol.cpp, which manages bitcoind's Tor onion service integration and P2P listening address advertising.

Factors: security/stability 2, bug 2, performance 0, user value 1, leverage 0

Reviewability: Stale: Needs rebase

  • Needs rebase due to merge conflicts against master

The PR has merge conflicts against master and requires a rebase.

Author status: Active; addressed review feedback with a push on 2026-09-04 but needs to rebase dirty branch.

Resolved concerns:

  • Space injection in ADD_ONION arguments alongside CRLF command injection was noted and tested by jeanpablojp; author added strict payload validation to block both.
  • Strict key format and service ID verification rather than character blacklisting was suggested by vasild; implemented in the Sep 4 push.
  • winterrdog raised whether explicit owner-only file permissions should be enforced when writing cached keys; vasild noted process umask already ensures safe permissions, and winterrdog closed the topic.

Agreement: Strong

  • Strong concept approval across active reviewers
  • Verified injection risks by testing hijacked inbound Tor connections (jeanpablojp)
  • Suggested strict whitelist validation instead of character blacklists (vasild)
  • Concept approval after exploring file permission safeguards (winterrdog)

Strong concept consensus; reviewers actively analyzed edge cases and the author addressed all feedback.

Three contributors gave Concept ACKs with substantive technical analysis. Reviewer requests for strict base64 parsing, space-injection guards, and service ID validation were completely integrated by the author.

  • winterrdog, jeanpablojp, and vasild posted Concept ACKs.
  • jeanpablojp demonstrated that injected Port= arguments diverted 15 of 30 incoming connections to the injected target.
  • vasild advised strict whitelist validation for ServiceID and Ed25519 base64 payloads rather than character blacklists, which author adopted.

Review verdicts (DrahtBot): 0

Files

95 lines under test/bench/ci.

  • test/functional/feature_torcontrol.py +80/-15
  • src/torcontrol.cpp +26/-2

Card

Validates Tor onion service IDs and private keys received from Tor control connections and cached on disk. It prevents an impersonated or hostile Tor control endpoint from injecting arbitrary control commands (via CRLF) or arguments (via spaces) when the node restarts and passes cached keys into ADD_ONION. Reviewers confirmed real exploitability where argument injection hijacks incoming onion traffic, and the author adopted strict format validation. Reviewers strongly support the change, though the branch currently requires a rebase.

Data

dossier JSON · extract JSON · model openrouter/google/gemini-3.8-flash, generated 2026-09-17T16:23, confidence high, input hash 9b06596e10e7f532