diff --git a/pkg/assessor/manifest/manifest.go b/pkg/assessor/manifest/manifest.go index 5355a6f..5573250 100644 --- a/pkg/assessor/manifest/manifest.go +++ b/pkg/assessor/manifest/manifest.go @@ -249,12 +249,25 @@ func assessHistory(index int, cmd types.History) []*AssessmentWithColumns { func useSudo(cmdSlices map[int][]string) bool { for _, cmdSlice := range cmdSlices { - if containsAll(cmdSlice, []string{"sudo"}) { - return true + for index, token := range cmdSlice { + if strings.Trim(token, "\"'();|") != "sudo" { + continue + } + if index == 0 { + return true + } + + previous := cmdSlice[index-1] + switch previous { + case "RUN", "-c", "then", "do", "else", "command", "exec": + return true + } + if strings.HasSuffix(previous, ";") || strings.HasSuffix(previous, "|") { + return true + } } } return false - } func useDistUpgrade(cmdSlices map[int][]string) bool { diff --git a/pkg/assessor/manifest/manifest_test.go b/pkg/assessor/manifest/manifest_test.go index a5c0694..467dd19 100644 --- a/pkg/assessor/manifest/manifest_test.go +++ b/pkg/assessor/manifest/manifest_test.go @@ -548,6 +548,51 @@ func TestUseDistUpgrade(t *testing.T) { } } +func TestUseSudo(t *testing.T) { + tests := map[string]struct { + cmdSlices map[int][]string + expected bool + }{ + "DirectCommand": { + cmdSlices: map[int][]string{ + 0: {"sudo", "apt-get", "update"}, + }, + expected: true, + }, + "ShellCommand": { + cmdSlices: map[int][]string{ + 0: {"/bin/sh", "-c", "sudo", "apt-get", "update"}, + }, + expected: true, + }, + "CommandAfterSemicolon": { + cmdSlices: map[int][]string{ + 0: {"/bin/sh", "-c", "set", "-eux;", "sudo", "apt-get", "update"}, + }, + expected: true, + }, + "FindNameArgument": { + cmdSlices: splitByCommands( + `/bin/sh -o pipefail -c find /bin /etc /lib /sbin /usr -xdev \( -iname hexdump -o -iname su -o -iname sudo \) -delete`, + ), + expected: false, + }, + "EchoArgument": { + cmdSlices: map[int][]string{ + 0: {"echo", "sudo"}, + }, + expected: false, + }, + } + + for testname, v := range tests { + actual := useSudo(v.cmdSlices) + if actual != v.expected { + t.Errorf("%s want: %t, got %t", testname, v.expected, actual) + } + } +} + func TestContainsThreshold(t *testing.T) { var tests = map[string]struct { heystack []string