Conversation
…error
AmountVisitor::visit_str mapped parse failures to
E::invalid_value(Unexpected::Str(value), &self), embedding the full
attacker-controlled input into the serde/JSON-RPC error message. On public
JSON-RPC methods that deserialize Amount, this makes error-path allocation
scale with the (body-size-bounded) invalid field length.
Use Unexpected::Other("string") so the error no longer reflects the input.
Behavior for valid amounts is unchanged.
Addresses AI-report Finding 85.
Co-authored-by: Cursor <cursoragent@cursor.com>
7036119 to
6326459
Compare
damip
left a comment
There was a problem hiding this comment.
@Leo-Besancon yes, keep E::custom, it is the best of the three: bounded and it says what is wrong. I checked that every message reachable from Amount::from_str is a constant: rust_decimal 1.37 parse_str_radix_10_exact only produces Error::from("Invalid decimal: ...") literals (no format! of the input anywhere in str.rs), the other Error variants have fixed Display text, and from_decimal uses four constant messages. AmountParseError is built nowhere else, so the new {0} in its Display cannot leak anything.
@modship your suggestion is superseded by Leo's commit (same idea, plus the actual reason), can you re-review?
One inline fix on the comment, then merge. No consensus or wire impact: serde Amount is JSON only (API, config, genesis files), the binary format uses the nom deserializer.
For the record: the same Unexpected::Str(value) line exists in version.rs, but Version is only ever in responses (NodeStatus.version), never deserialized from untrusted input. Not worth touching.
Summary
AmountVisitor::visit_strmapped parse failures toE::invalid_value(Unexpected::Str(value), &self), embedding the full, attacker-controlled input string into the serde/JSON-RPC error message. On public JSON-RPC methods that deserializeAmount(e.g.execute_read_only_call), this makes error-path memory allocation scale with the invalid field length (bounded bymax_request_body_size, but still avoidable amplification).Addresses AI-report Finding 85 (severity: minor).
Fix
Use
Unexpected::Other("string")instead ofUnexpected::Str(value), so the error no longer reflects the rejected input.Why this is non-breaking
Amountvalues deserialize identically.Testing
test_valid_amount_still_deserializes— valid input still parses.test_invalid_amount_error_does_not_reflect_input— a 4096-char bogus string is absent from the error message.cargo test -p massa_models --features test-exports amount: 2/2 pass.cargo clippy -p massa_models --all-targets --features test-exports: clean.cargo fmt: clean.Checklist
Made with Cursor