What changed, and why it matters
This commit tightens up error messages in Bitcoin Core's I2P (anonymous networking) code. Previously, error messages could accidentally include the full text of a SAM request that may carry the user's I2P private key, or the full raw reply from an I2P router. The patch keeps the error useful by still referencing the redacted request, but stops echoing the sensitive request body and unescaped router replies into logs. It is a defensive information-disclosure fix, not a change to network behavior.
Treat as a low-severity information-disclosure hardening patch. Review whether any other I2P or P2P error paths log raw request/reply contents, and ensure private key material is consistently redacted in logs. No urgent network upgrade is required, but node operators running I2P should update in due course.
Security signals we found
Sensitive data in error/log messages: SAM SESSION CREATE request may contain I2P private key
Unescaped external input in error/log messages: raw SAM reply bytes from router
Information disclosure via logging
Defensive hardening with no intended network behavior change
Evidence from the diff
In src/i2p.cpp, two exception messages are changed. In Session::Reply::Get(), the thrown runtime_error no longer interpolates request and full into the message; it now only names the missing key and the redacted request. In Session::SendRequestAndGetReply(), the non-OK RESULT error no longer includes reply.full; it now only references reply.request. The commit message explicitly states the goal is to avoid logging the private-key-bearing request text and unescaped router-controlled reply bytes. No protocol or network behavior change is intended.
Changed components
src/i2p.cppBitcoin Core I2P SAM session handlingSession::Reply::Get()Session::SendRequestAndGetReply()Inspect captured patch +2 / −2
diff --git a/src/i2p.cpp b/src/i2p.cpp
index 04093ea1..03513576 100644
--- a/src/i2p.cpp
+++ b/src/i2p.cpp
@@ -285,7 +285,7 @@ std::string Session::Reply::Get(const std::string& key) const
const auto& pos = keys.find(key);
if (pos == keys.end() || !pos->second.has_value()) {
throw std::runtime_error(
- strprintf("Missing %s= in the reply to \"%s\": \"%s\"", key, request, full));
+ strprintf("Missing %s= in the reply to \"%s\"", key, request));
}
return pos->second.value();
}
@@ -320,7 +320,7 @@ Session::Reply Session::SendRequestAndGetReply(const Sock& sock,
if (check_result_ok && reply.Get("RESULT") != "OK") {
throw std::runtime_error(
- strprintf("Unexpected reply to \"%s\": \"%s\"", request, reply.full));
+ strprintf("Reply to \"%s\": had a RESULT not equal to OK.", reply.request));
}
return reply;
Why this scored 35/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.