fix(subtreevalidation): bound HTTP body reads when fetching subtree data#772
Conversation
|
🤖 Claude Code Review Status: Complete Summary: Security fix correctly addresses HIGH-severity unbounded memory allocation vulnerability. Implementation is sound with comprehensive testing. Current Review: Key strengths:
Minor observation (not blocking): History:
|
Benchmark Comparison ReportBaseline: Current: Summary
All benchmark results (sec/op)
Threshold: >10% with p < 0.05 | Generated: 2026-05-19 10:10 UTC |
|
|
||
| server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
| assert.Equal(t, http.MethodPost, r.Method) | ||
| assert.Equal(t, "application/json", r.Header.Get("Content-Type")) |
There was a problem hiding this comment.
[Minor] Test assertion mismatch
The test expects Content-Type: application/json but DoHTTPRequestBounded sets Content-Type: application/octet-stream for POST requests (util/http.go:288).
This matches existing DoHTTPRequest behavior. Per util/http.go:279-284, binary payloads use application/octet-stream to avoid WAF issues.
Fix: Change line 534 to check for application/octet-stream instead.
…efs #4571) Add TestCheckBlockSubtrees_OversizedBody to cover the third peer-fetch call site at check_block_subtrees.go:218, mirroring the existing fetchSubtreeFromPeer and getSubtreeTxHashes coverage so all three peer- fetch paths fail closed on oversized responses. Align TestDoHTTPRequestBounded_POST content-type assertion with the application/octet-stream default introduced upstream by bsv-blockchain#829, surfaced after rebasing onto main.
021641a to
23da07e
Compare
|



Closes #4571.
Summary
util.DoHTTPRequestusesio.ReadAllon the response body with no size limit. Two subtree-fetching callers inservices/subtreevalidation/(getSubtreeTxHashesat SubtreeValidation.go:893 and the missing-subtree path at check_block_subtrees.go:214) accept peer-provided URLs, so a malicious peer can stream up to 60 seconds of unbounded memory allocation per request. Severity HIGH because the attack is remote-triggerable.Fix
Adds
util.DoHTTPRequestBounded(ctx, url, maxBytes, body...)that mirrorsDoHTTPRequestbut wraps the body inio.LimitReader(body, maxBytes+1)and returns a typed error if the response exceedsmaxBytes. Both subtree-fetching call sites now passmaxSubtreeBytes = MaximumMerkleItemsPerSubtree * chainhash.HashSize(32 MB by default).Other
DoHTTPRequestcall sites (block fetches, header fetches inservices/blockvalidation/) are out of scope — they have different size profiles and may be addressed in separate audit follow-ups.Test plan
DoHTTPRequestBounded: happy path, body equal to limit, body exceeds limit (typed error returned, no over-allocation).go test -race ./util/...passes.go test -race -tags testtxmetacache ./services/subtreevalidation/...passes.