Skip to content

fix(api): tighten json parsing limits#6844

Merged
kuny0707 merged 6 commits into
tronprotocol:release_v4.8.2from
317787106:fix/fix_json_param
Jun 17, 2026
Merged

fix(api): tighten json parsing limits#6844
kuny0707 merged 6 commits into
tronprotocol:release_v4.8.2from
317787106:fix/fix_json_param

Conversation

@317787106

@317787106 317787106 commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator

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_DEPTH from 100 to 20. This shared constant bounds the nesting depth on both:

    • the HTTP wallet API — Jackson factory in JSON.java and the JsonFormat protobuf parser, and
    • the JSON-RPC API — JsonRpcServlet.
  • On the JSON-RPC endpoint, when a Jackson StreamConstraintsException is hit (i.e. a StreamReadConstraints limit 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:

    nesting depth (21) exceeds the maximum allowed (20, from `StreamReadConstraints.getMaxNestingDepth()`)
    
  • In TronJsonRpcImpl.buildCreateSmartContractTransaction, change the exception handling around JsonFormat.merge(...) from catch (JsonFormat.ParseException | StackOverflowError e) to catch (Exception e):

    • StackOverflowError is dropped because the nesting depth is now capped at 20, so the recursive-parse stack overflow it used to guard against is no longer reachable.
    • Catching Exception keeps this call site consistent with how the other servlets handle JsonFormat.merge(...) failures (the HTTP servlets all wrap it in catch (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_COUNT is left unchanged at 100_000.

The new MAX_NESTING_DEPTH value 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:

  • Unit Tests
  • Manual Testing

Follow up

Extra details

@halibobo1205 halibobo1205 added this to the GreatVoyage-v4.8.2 milestone Jun 16, 2026
@halibobo1205 halibobo1205 added the topic:api rpc/http related issue label Jun 16, 2026
@317787106 317787106 changed the title fix(api): decrease MAX_NESTING_DEPTH and MAX_TOKEN_COUNT for json fix(api): tighten json parsing limits to mitigate dos Jun 16, 2026
@317787106 317787106 changed the title fix(api): tighten json parsing limits to mitigate dos fix(api): tighten json parsing limits Jun 16, 2026
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;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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.

@317787106 317787106 Jun 17, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
@kuny0707 kuny0707 merged commit 95d84d3 into tronprotocol:release_v4.8.2 Jun 17, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

topic:api rpc/http related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants