Conversation
Reject claimed vector/deque/flat_* sizes that cannot fit in stream remaining() before resize/reserve, so a short P2P/SHiP frame advertising MAX_NUM_ARRAY_ELEMENTS cannot force a ~32MiB allocation. Wire format is unchanged for valid payloads. Refuse unauthenticated producer_rw/snapshot APIs on non-loopback listeners unless --http-expose-nonloopback-producer-api is set, refuse CORS on that combination without --http-allow-control-plane-cors, and reject Access-Control-Allow-Origin=* with credentials. Co-authored-by: Igor Lins e Silva <igorls@users.noreply.github.com>
id_list_modes is not FC_REFLECT_ENUM, so fc::raw writes sizeof(enum) rather than int64_t. Packing 8 bytes misaligned the claimed ids size and would not exercise the F1 remaining() check. Co-authored-by: Igor Lins e Silva <igorls@users.noreply.github.com>
Clang rejects hash("a") because it instantiates hash<char[N]> and
fc::raw::pack is then overloaded for both T(&)[N] and const char*.
Use the std::string overload instead.
Co-authored-by: Igor Lins e Silva <igorls@users.noreply.github.com>
T dummy{} is copy-list-initialization and cannot call explicit
default constructors. Unpacking vector<book> failed to compile
because shared_cow_vector() is explicit. Use T dummy; instead.
Co-authored-by: Igor Lins e Silva <igorls@users.noreply.github.com>
Keep F1 short-read failures as fc::out_of_range_exception so existing unpack tests and catch sites stay compatible. Read CORS origin and credentials from the variables_map in http_plugin::plugin_initialize because option notifiers may run after initialize. Co-authored-by: Igor Lins e Silva <igorls@users.noreply.github.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.
Follow-up to the v1.2.3-alpha2 remediations in #3. Completes the incomplete Issue-4 mitigation (F1) and hardens unauthenticated producer control-plane HTTP (F2). No consensus, ABI, wire, or RPC response-shape changes for valid traffic.
F1 — unpack allocation amplification (Medium)
fc::bounded_datastreamstops cross-frame P2P reads, butfc::raw::unpackforstd::vector/deque/flat_*still didresize/reserve(claimed_size)before reading elements. A ~25-bytenotice_messagecan claimids.size() == MAX_NUM_ARRAY_ELEMENTS(1<<20) and force ~32MiBvector<sha256>before the short-read fails. The same path is reachable from SHiP session unpack.Fix: before resize/reserve, assert that
count * pack_size(T{})fits ins.remaining()when the stream reports a trustworthy remaining count (in-memorydatastreamandbounded_datastream). Default-constructedTis the minimum serialized size for the types on these paths (empty string/vector = 1-byte size prefix;sha256= 32). Empty structs that pack to 0 skip the check so valid zero-payload vectors are not rejected.This is fail-closed for malicious claims only. Valid payloads unpack unchanged.
Tests:
libraries/libfc/test/io/test_unpack_bounds.cpp— short frames with huge claimed sizes throwfc::assert_exceptionwithout a large RSS jump; valid vectors still round-trip.plugins/net_plugin/tests/test_net_plugin.cpp— short bounded P2Pnotice_messagewithids.size() == MAX_NUM_ARRAY_ELEMENTSis rejected.F2 — producer_api_plugin unauthenticated HTTP (Medium, ops)
Destructive producer RPCs (
pause/resume/snapshot/runtime options/feature schedule/whitelists) sit on the sharedhttp_pluginlistener with no auth. The previous warning only fired when the category was not loopback.Hardening (safe for local tooling):
http-server-address(127.0.0.1) and UNIX sockets keep working with no new flags.producer_rw/snapshotis refused at startup unless--http-expose-nonloopback-producer-api.--http-allow-control-plane-cors.Access-Control-Allow-Origin: *+Access-Control-Allow-Credentials: trueis refused globally (invalid CORS, CSRF amplifier).Residual risks (not invented as new vulns)
net_api_pluginnet_rw(connect/disconnect) is the same warn-only unauthenticated pattern; not changed here.cfileunpack still has noremaining(); the new check is skipped there (local/trusted inputs).producer_roremains unauthenticated (read-only).Compatibility
No protocol-rule, ABI, or RPC/SHiP response-shape changes. Operators who intentionally bind producer APIs to a public HTTP address must add
--http-expose-nonloopback-producer-api(and--http-allow-control-plane-corsif they also set a CORS origin).