Reject malformed ACL and user-list records

This commit is contained in:
Brandon McGinty (chatgpt)
2026-08-09 14:44:42 -04:00
committed by Brandon McGinty
parent 3e9c9e7a81
commit 1fa96d4f15
3 changed files with 31 additions and 1 deletions
+1 -1
View File
@@ -161,7 +161,7 @@ Priority 2: protocol and data correctness
not remove channel from the Links maps of old peers. Remove reciprocal old not remove channel from the Links maps of old peers. Remove reciprocal old
links before replacement and add link add/remove/full-replacement tests. links before replacement and add link add/remove/full-replacement tests.
20. Malformed protobuf fields can panic handlers [x] 20. Malformed protobuf fields can panic handlers
File: gumble/gumble/handlers.go File: gumble/gumble/handlers.go
Several optional proto fields are dereferenced without validation, notably Several optional proto fields are dereferenced without validation, notably
ACL group.Name and UserList_User.UserId. Validate required fields before ACL group.Name and UserList_User.UserId. Validate required fields before
+24
View File
@@ -0,0 +1,24 @@
package gumble
import (
"testing"
"git.stormux.org/storm/barnard/gumble/gumble/MumbleProto"
"google.golang.org/protobuf/proto"
)
// Regression: an ACL group without its optional name dereferenced nil in the
// TCP handler, allowing malformed server data to crash the client.
func TestACLRejectsGroupWithoutName(t *testing.T) {
id := uint32(1)
packet := &MumbleProto.ACL{ChannelId: &id, Groups: []*MumbleProto.ACL_ChanGroup{{}}}
data, err := proto.MarshalOptions{AllowPartial: true}.Marshal(packet)
if err != nil {
t.Fatal(err)
}
c := &Client{Config: NewConfig(), Channels: make(Channels)}
c.Channels.create(id)
if err := c.handleACL(data); err == nil {
t.Fatal("accepted malformed ACL group")
}
}
+6
View File
@@ -899,6 +899,9 @@ func (c *Client) handleACL(buffer []byte) error {
if packet.Groups != nil { if packet.Groups != nil {
acl.Groups = make([]*ACLGroup, 0, len(packet.Groups)) acl.Groups = make([]*ACLGroup, 0, len(packet.Groups))
for _, group := range packet.Groups { for _, group := range packet.Groups {
if group == nil || group.Name == nil {
return errInvalidProtobuf
}
aclGroup := &ACLGroup{ aclGroup := &ACLGroup{
Name: *group.Name, Name: *group.Name,
Inherited: group.GetInherited(), Inherited: group.GetInherited(),
@@ -1079,6 +1082,9 @@ func (c *Client) handleUserList(buffer []byte) error {
} }
for _, user := range packet.Users { for _, user := range packet.Users {
if user == nil || user.UserId == nil {
return errInvalidProtobuf
}
registeredUser := &RegisteredUser{ registeredUser := &RegisteredUser{
UserID: *user.UserId, UserID: *user.UserId,
} }