fix: Validate the connect ip parameter - #7954
Draft
SoubeDev wants to merge 2 commits into
Draft
Conversation
doConnect checked that ip was present but never that it was a string, while the sibling port field is type checked with isConvertibleTo. The unguarded asString() then failed in two different ways. For an array or an object, asString() hits JSON_ASSERT_MESSAGE, which throws json::Error. The throw was swallowed by the dispatch catch-all, so a malformed value produced a generic internal error rather than invalidParams, and the request was recorded as a server fault in the perf log. Every scalar was worse, because it was silently coerced instead: 42 became "42", 1.5 became "1.500000", true became "true" and null became "". None of those parse as an address, so isUnspecified() was true and the connect was skipped, yet the handler still returned "attempting connection to IP:true port: 2459". The caller was told a connection had been attempted when none ever was. Guard the conversion with an isString() check and return invalidParams when it fails, reusing RPC::expectedFieldError so the error matches the family the port path already returns. The commandline is unaffected. RPCParser::parseConnect always assigns jss::ip from a std::string, whether the argument is given as ip and port or as a single ip:port, so the new check can never fire there. Connect_test only covered the standalone rejection, which returns before any parameter is read. Split it into standalone, missing ip and invalid ip cases, with a helper that leaves standalone mode so the parameter checks become reachable; connect is a Condition::NoCondition command, so no other part of dispatch reads that flag. Fixes XRPLF#6744 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
doConnect checked that ip was present but never that it was a string, while the sibling port field is type checked with isConvertibleTo. The unguarded asString() then failed in two different ways.
For an array or an object, asString() hits JSON_ASSERT_MESSAGE, which throws json::Error. The throw was swallowed by the dispatch catch-all, so a malformed value produced a generic internal error rather than invalidParams, and the request was recorded as a server fault in the perf log.
Every scalar was worse, because it was silently coerced instead: 42 became "42", 1.5 became "1.500000", true became "true" and null became "". None of those parse as an address, so isUnspecified() was true and the connect was skipped, yet the handler still returned "attempting connection to IP:true port: 2459". The caller was told a connection had been attempted when none ever was.
Guard the conversion with an isString() check and return invalidParams when it fails, reusing RPC::expectedFieldError so the error matches the family the port path already returns.
The commandline is unaffected. RPCParser::parseConnect always assigns jss::ip from a std::string, whether the argument is given as ip and port or as a single ip:port, so the new check can never fire there.
Connect_test only covered the standalone rejection, which returns before any parameter is read. Split it into standalone, missing ip and invalid ip cases, with a helper that leaves standalone mode so the parameter checks become reachable; connect is a Condition::NoCondition command, so no other part of dispatch reads that flag.
Fixes #6744
High Level Overview of Change
Context of Change
API Impact
libxrplchange (any change that may affectlibxrplor dependents oflibxrpl)