Skip to content

Commit 148de7d

Browse files
matthew-pilotTeoSlayer
authored andcommitted
fix(eventstream): reject events with invalid UTF-8 topic (PILOT-277)
ReadEvent now validates topic bytes with utf8.Valid() before casting to string. Without this check, an attacker can craft a topic with invalid UTF-8 that survives transport unchanged but gets silently mangled by json.Marshal (replacing invalid sequences with U+FFFD). This can be exploited to escape audit redaction (PILOT-284) — the wire-observed bytes differ from the JSON-logged value, yet both map to the same Go map key. Closes PILOT-277 (eventstream half)
1 parent 2eaf1f5 commit 148de7d

2 files changed

Lines changed: 21 additions & 0 deletions

File tree

eventstream.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"encoding/binary"
77
"fmt"
88
"io"
9+
"unicode/utf8"
910
)
1011

1112
// Event is a typed message published to the event stream.
@@ -58,5 +59,9 @@ func ReadEvent(r io.Reader) (*Event, error) {
5859
return nil, err
5960
}
6061

62+
if !utf8.Valid(topic) {
63+
return nil, fmt.Errorf("topic contains invalid UTF-8")
64+
}
65+
6166
return &Event{Topic: string(topic), Payload: payload}, nil
6267
}

zz_event_wire_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,19 @@ func TestEventPayloadTooLarge(t *testing.T) {
143143
t.Fatal("expected error for oversized payload, got nil")
144144
}
145145
}
146+
147+
func TestEventTopicInvalidUTF8(t *testing.T) {
148+
t.Parallel()
149+
var buf bytes.Buffer
150+
// Craft topic with invalid UTF-8: byte 0xFF is never valid
151+
invalidTopic := []byte{0x48, 0xFF, 0x69} // H + invalid + i
152+
binary.Write(&buf, binary.BigEndian, uint16(len(invalidTopic)))
153+
buf.Write(invalidTopic)
154+
// Valid payload
155+
binary.Write(&buf, binary.BigEndian, uint32(0))
156+
157+
_, err := eventstream.ReadEvent(&buf)
158+
if err == nil {
159+
t.Fatal("expected error for invalid UTF-8 topic, got nil")
160+
}
161+
}

0 commit comments

Comments
 (0)