fix(dataexchange): reject FILE frames with invalid UTF-8 filename (PILOT-277)#11
fix(dataexchange): reject FILE frames with invalid UTF-8 filename (PILOT-277)#11matthew-pilot wants to merge 1 commit into
Conversation
…LOT-277) ReadFrame now validates filename bytes with utf8.Valid() before casting to string. Without this check, an attacker can send a FILE frame with invalid UTF-8 in the filename field that survives transport unchanged but gets silently mangled by downstream json.Marshal (replacing invalid sequences with U+FFFD). This can be exploited to escape audit redaction — the wire-observed bytes differ from the JSON-logged value. Closes PILOT-277 (dataexchange half)
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
🦾 Matthew PR Status — #11Title: fix(dataexchange): reject FILE frames with invalid UTF-8 filename (PILOT-277) TicketsLabelsNone Files Changed
Next Actions
🦾 Auto-generated status check by matthew-pr-worker |
🦾 Matthew PR Explain — #11What this PR doesfix(dataexchange): reject FILE frames with invalid UTF-8 filename (PILOT-277) Scope
TicketsFiles
Review Notes
🦾 Auto-generated explain by matthew-pr-worker |
🦾 Matthew PR Status — #11Title: fix(dataexchange): reject FILE frames with invalid UTF-8 filename (PILOT-277) TicketsLabelsNone Files Changed
Next Actions
🦾 Auto-generated status check by matthew-pr-worker |
🦾 Matthew PR Explain — #11What this PR doesfix(dataexchange): reject FILE frames with invalid UTF-8 filename (PILOT-277) Scope
TicketsFiles
Review Notes
🦾 Auto-generated explain by matthew-pr-worker |
What failed
ReadFrameindataexchange.go:120casts raw network bytes to string vianame := string(payload[2:2+nameLen])without UTF-8 validation. An attacker can send a FILE frame with invalid UTF-8 in the filename bytes. Downstreamjson.Marshalsilently replaces invalid sequences with U+FFFD, creating a discrepancy between wire-observed and JSON-logged values exploitable as an audit-redaction escape (PILOT-284).Why this fix
Added
utf8.Valid(nameBytes)check before thestring()cast. If validation fails,ReadFramereturns an error with a clear message. This rejects malformed input at the protocol boundary rather than allowing silent corruption.Verification
go build ./...✓go vet ./...✓go test ./...✓ (all tests pass, including newTestFrameFileInvalidUTF8)Scope
dataexchange.go: +7/-1 lines (import + validation check, refactoredname := string(...)intonameBytesvariable)zz_frame_test.go: +28 lines (new test with raw wire-format crafting)Both files: 2 files, +34/-1 LoC. Small tier.
Closes PILOT-277 (dataexchange half)