fix(api): tighten json parsing limits#6844
Conversation
| public static final int MAX_NESTING_DEPTH = 100; | ||
| public static final int MAX_TOKEN_COUNT = 100_000; | ||
| public static final int MAX_NESTING_DEPTH = 20; | ||
| public static final int MAX_HTTP_TOKEN_COUNT = 5_000; |
There was a problem hiding this comment.
[MUST] Keep the 5,000-token limit off internal response-shaping parses.
MAX_HTTP_TOKEN_COUNT is applied to the shared org.tron.json.JSON mapper, so it not only constrains untrusted HTTP request parsing. Several HTTP response helpers first serialize node-generated protobuf JSON with JsonFormat.printToString(...), then parse that generated string back through JSONObject.parseObject(...) / JSON.parseObject(...) to reshape the response before writing it.
Examples include Util.printTransactionIdList, Util.printTransactionList, Util.printTransactionExtention, and GetTransactionInfoByBlockNumServlet#convertLogAddressToTronAddress. Those internal parses now inherit the 5,000-token cap. A large but valid node-generated response, such as a pending transaction-id list or other transaction-heavy response, can fail during response construction even though the limit was intended to reject oversized inbound JSON.
Please separate the constrained ingress parser from the internal JSON mapper, or avoid reparsing generated response JSON on these paths.
There was a problem hiding this comment.
I check the examples above, none of these string have been used by JSONObject.parseObject(...) / JSON.parseObject(...) again. The biggest reference may be JSONObject.parseObject(JsonFormat.printToString(transactionInfo, visible)). It's far smaller than 5000. Since PR #6845 has already fixed the stack overflow issue caused by JsonFormat's tail-recursive parsing, parsing JSON with a very large number of tokens no longer leads to increased CPU utilization. As a result, further restricting MAX_TOKEN_COUNT would provide limited benefit, so we decided not to modify this value.
…e errors Verify the new branch in JsonRpcServlet that surfaces the specific StreamConstraintsException message (nesting depth / token count) instead of the generic "JSON parse error", while non-constraint parse failures keep the generic message. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
What does this PR do?
To reduce the attack surface for DoS via overly large / deeply nested JSON payloads, this PR tightens the JSON parsing limits and improves the error reporting on the public APIs.
Specifically:
Lowers
MAX_NESTING_DEPTHfrom100to20. This shared constant bounds the nesting depth on both:JSON.javaand theJsonFormatprotobuf parser, andJsonRpcServlet.On the JSON-RPC endpoint, when a Jackson
StreamConstraintsExceptionis hit (i.e. aStreamReadConstraintslimit such as nesting depth or token count is exceeded), return the specific constraint message instead of the generic"JSON parse error", so callers can tell which limit was hit. For example:In
TronJsonRpcImpl.buildCreateSmartContractTransaction, change the exception handling aroundJsonFormat.merge(...)fromcatch (JsonFormat.ParseException | StackOverflowError e)tocatch (Exception e):StackOverflowErroris dropped because the nesting depth is now capped at20, so the recursive-parse stack overflow it used to guard against is no longer reachable.Exceptionkeeps this call site consistent with how the other servlets handleJsonFormat.merge(...)failures (the HTTP servlets all wrap it incatch (Exception e)). Any ABI parse failure is therefore surfaced uniformly as invalid-params (-32602,"invalid abi") instead of escaping as a generic internal error.MAX_TOKEN_COUNTis left unchanged at100_000.The new
MAX_NESTING_DEPTHvalue is an evaluation result derived from analyzing historical requests, so legitimate traffic stays within the limit while overly deep payloads are rejected early.Why are these changes required?
The previous nesting limit (
100) was much larger than what real-world requests need. Such a large bound still allows an attacker to submit deeply nested JSON payloads that consume significant CPU/memory during parsing, amplifying the impact of a DDoS attack. Tightening it to a value based on observed traffic reduces that attack surface while keeping normal requests unaffected. Returning the specific constraint message on JSON-RPC also makes the failure mode observable and easier to diagnose.This PR has been tested by:
Follow up
Extra details