From 6d53161236cb414141ab9def281b531c3182ec0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Thu, 5 Nov 2026 14:36:31 +0100 Subject: [PATCH 1/2] user: Fix GetAdditionalGroups panic on empty group name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Passing an empty string in additionalGroups caused a nil pointer dereference. Signed-off-by: Paweł Gronowski --- user/user.go | 3 +++ user/user_test.go | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/user/user.go b/user/user.go index 48c34a8b..580a55b0 100644 --- a/user/user.go +++ b/user/user.go @@ -398,6 +398,9 @@ func GetAdditionalGroups(additionalGroups []string, group io.Reader) ([]int, err if err != nil { return nil, err } + if groupArg == nil { + return nil, fmt.Errorf("unable to find group %s: %w", ag, ErrNoGroupEntries) + } addtlGroups = append(addtlGroups, *groupArg) } diff --git a/user/user_test.go b/user/user_test.go index 8d08e1c5..a99b24a8 100644 --- a/user/user_test.go +++ b/user/user_test.go @@ -590,6 +590,12 @@ this is just some garbage data expected: nil, hasError: true, }, + { + doc: "empty group name", + groups: []string{"adm", ""}, + expected: nil, + hasError: true, + }, { doc: "group with numeric id", groups: []string{"43"}, From 2588f62be041ba3d76cb89c6a4ab08ed80a46d1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Mon, 9 Nov 2026 13:25:29 +0100 Subject: [PATCH 2/2] user: Reject empty names in parseUserArg and parseGroupArg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both helpers now return an error for an empty name instead of "nil, nil", and their callers check for an empty name first. Behavior of GetExecUser and GetAdditionalGroups is unchanged. Signed-off-by: Paweł Gronowski --- user/user.go | 23 ++++++++++++++--------- user/user_utils.go | 10 ++-------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/user/user.go b/user/user.go index 580a55b0..4bf8762c 100644 --- a/user/user.go +++ b/user/user.go @@ -303,13 +303,21 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) ( // Convert usr and grp to be numeric, so we don't have to execute // Atoi *twice* for each iteration over lines. - userArg, err := parseUserArg(usr) - if err != nil { - return nil, err + var userArg *userArg + if usr != "" { + var err error + userArg, err = parseUserArg(usr) + if err != nil { + return nil, err + } } - groupArg, err := parseGroupArg(grp) - if err != nil { - return nil, err + var groupArg *groupArg + if grp != "" { + var err error + groupArg, err = parseGroupArg(grp) + if err != nil { + return nil, err + } } // Find the matching user. @@ -398,9 +406,6 @@ func GetAdditionalGroups(additionalGroups []string, group io.Reader) ([]int, err if err != nil { return nil, err } - if groupArg == nil { - return nil, fmt.Errorf("unable to find group %s: %w", ag, ErrNoGroupEntries) - } addtlGroups = append(addtlGroups, *groupArg) } diff --git a/user/user_utils.go b/user/user_utils.go index 8084d3b0..e0938bd8 100644 --- a/user/user_utils.go +++ b/user/user_utils.go @@ -71,12 +71,9 @@ type userArg struct { } // parseUserArg parses a user argument as either a user name or UID. -// -// If name is empty, parseUserArg returns "nil, nil" to indicate that no user -// argument was specified. func parseUserArg(name string) (*userArg, error) { if name == "" { - return nil, nil + return nil, errors.New("empty user") } uid, isNumeric, err := parseNumeric(name) if err != nil { @@ -102,12 +99,9 @@ type groupArg struct { } // parseGroupArg parses a group argument as either a group name or GID. -// -// If name is empty, parseGroupArg returns "nil, nil" to indicate that no group -// argument was specified. func parseGroupArg(name string) (*groupArg, error) { if name == "" { - return nil, nil + return nil, errors.New("empty group") } gid, isNumeric, err := parseNumeric(name) if err != nil {