github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/detector/ospkg/alpine/alpine_test.go (about)

     1  package alpine_test
     2  
     3  import (
     4  	"sort"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  	"github.com/stretchr/testify/require"
    10  	fake "k8s.io/utils/clock/testing"
    11  
    12  	"github.com/aquasecurity/trivy-db/pkg/db"
    13  	dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
    14  	"github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability"
    15  	"github.com/devseccon/trivy/pkg/dbtest"
    16  	"github.com/devseccon/trivy/pkg/detector/ospkg/alpine"
    17  	ftypes "github.com/devseccon/trivy/pkg/fanal/types"
    18  	"github.com/devseccon/trivy/pkg/types"
    19  )
    20  
    21  func TestScanner_Detect(t *testing.T) {
    22  	type args struct {
    23  		osVer string
    24  		repo  *ftypes.Repository
    25  		pkgs  []ftypes.Package
    26  	}
    27  	tests := []struct {
    28  		name     string
    29  		args     args
    30  		fixtures []string
    31  		want     []types.DetectedVulnerability
    32  		wantErr  string
    33  	}{
    34  		{
    35  			name: "happy path",
    36  			fixtures: []string{
    37  				"testdata/fixtures/alpine.yaml",
    38  				"testdata/fixtures/data-source.yaml",
    39  			},
    40  			args: args{
    41  				osVer: "3.10.2",
    42  				pkgs: []ftypes.Package{
    43  					{
    44  						Name:       "ansible",
    45  						Version:    "2.6.4",
    46  						SrcName:    "ansible",
    47  						SrcVersion: "2.6.4",
    48  						Layer: ftypes.Layer{
    49  							DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
    50  						},
    51  					},
    52  					{
    53  						Name:       "invalid",
    54  						Version:    "invalid", // skipped
    55  						SrcName:    "invalid",
    56  						SrcVersion: "invalid",
    57  					},
    58  				},
    59  			},
    60  			want: []types.DetectedVulnerability{
    61  				{
    62  					PkgName:          "ansible",
    63  					VulnerabilityID:  "CVE-2019-10217",
    64  					InstalledVersion: "2.6.4",
    65  					FixedVersion:     "2.8.4-r0",
    66  					Layer: ftypes.Layer{
    67  						DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
    68  					},
    69  					DataSource: &dbTypes.DataSource{
    70  						ID:   vulnerability.Alpine,
    71  						Name: "Alpine Secdb",
    72  						URL:  "https://secdb.alpinelinux.org/",
    73  					},
    74  				},
    75  				{
    76  					PkgName:          "ansible",
    77  					VulnerabilityID:  "CVE-2021-20191",
    78  					InstalledVersion: "2.6.4",
    79  					FixedVersion:     "",
    80  					Layer: ftypes.Layer{
    81  						DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
    82  					},
    83  					DataSource: &dbTypes.DataSource{
    84  						ID:   vulnerability.Alpine,
    85  						Name: "Alpine Secdb",
    86  						URL:  "https://secdb.alpinelinux.org/",
    87  					},
    88  				},
    89  			},
    90  		},
    91  		{
    92  			name: "contain rc",
    93  			fixtures: []string{
    94  				"testdata/fixtures/alpine.yaml",
    95  				"testdata/fixtures/data-source.yaml",
    96  			},
    97  			args: args{
    98  				osVer: "3.10",
    99  				pkgs: []ftypes.Package{
   100  					{
   101  						Name:       "jq",
   102  						Version:    "1.6-r0",
   103  						SrcName:    "jq",
   104  						SrcVersion: "1.6-r0",
   105  					},
   106  				},
   107  			},
   108  			want: []types.DetectedVulnerability{
   109  				{
   110  					PkgName:          "jq",
   111  					VulnerabilityID:  "CVE-2020-1234",
   112  					InstalledVersion: "1.6-r0",
   113  					FixedVersion:     "1.6-r1",
   114  					DataSource: &dbTypes.DataSource{
   115  						ID:   vulnerability.Alpine,
   116  						Name: "Alpine Secdb",
   117  						URL:  "https://secdb.alpinelinux.org/",
   118  					},
   119  				},
   120  			},
   121  		},
   122  		{
   123  			name: "contain pre",
   124  			fixtures: []string{
   125  				"testdata/fixtures/alpine.yaml",
   126  				"testdata/fixtures/data-source.yaml",
   127  			},
   128  			args: args{
   129  				osVer: "3.10",
   130  				pkgs: []ftypes.Package{
   131  					{
   132  						Name:       "test",
   133  						Version:    "0.1.0_alpha",
   134  						SrcName:    "test-src",
   135  						SrcVersion: "0.1.0_alpha",
   136  						Layer: ftypes.Layer{
   137  							DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
   138  						},
   139  					},
   140  				},
   141  			},
   142  			want: []types.DetectedVulnerability{
   143  				{
   144  					VulnerabilityID:  "CVE-2030-0002",
   145  					PkgName:          "test",
   146  					InstalledVersion: "0.1.0_alpha",
   147  					FixedVersion:     "0.1.0_alpha2",
   148  					Layer: ftypes.Layer{
   149  						DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
   150  					},
   151  					DataSource: &dbTypes.DataSource{
   152  						ID:   vulnerability.Alpine,
   153  						Name: "Alpine Secdb",
   154  						URL:  "https://secdb.alpinelinux.org/",
   155  					},
   156  				},
   157  			},
   158  		},
   159  		{
   160  			name: "repository is newer than OS version",
   161  			fixtures: []string{
   162  				"testdata/fixtures/alpine.yaml",
   163  				"testdata/fixtures/data-source.yaml",
   164  			},
   165  			args: args{
   166  				osVer: "3.9.3",
   167  				repo: &ftypes.Repository{
   168  					Family:  ftypes.Alpine,
   169  					Release: "3.10",
   170  				},
   171  				pkgs: []ftypes.Package{
   172  					{
   173  						Name:       "jq",
   174  						Version:    "1.6-r0",
   175  						SrcName:    "jq",
   176  						SrcVersion: "1.6-r0",
   177  					},
   178  				},
   179  			},
   180  			want: []types.DetectedVulnerability{
   181  				{
   182  					PkgName:          "jq",
   183  					VulnerabilityID:  "CVE-2020-1234",
   184  					InstalledVersion: "1.6-r0",
   185  					FixedVersion:     "1.6-r1",
   186  					DataSource: &dbTypes.DataSource{
   187  						ID:   vulnerability.Alpine,
   188  						Name: "Alpine Secdb",
   189  						URL:  "https://secdb.alpinelinux.org/",
   190  					},
   191  				},
   192  			},
   193  		},
   194  		{
   195  			name: "Get returns an error",
   196  			fixtures: []string{
   197  				"testdata/fixtures/invalid.yaml",
   198  				"testdata/fixtures/data-source.yaml",
   199  			},
   200  			args: args{
   201  				osVer: "3.10.2",
   202  				pkgs: []ftypes.Package{
   203  					{
   204  						Name:       "jq",
   205  						Version:    "1.6-r0",
   206  						SrcName:    "jq",
   207  						SrcVersion: "1.6-r0",
   208  					},
   209  				},
   210  			},
   211  			wantErr: "failed to get alpine advisories",
   212  		},
   213  		{
   214  			name: "No src name",
   215  			fixtures: []string{
   216  				"testdata/fixtures/alpine.yaml",
   217  				"testdata/fixtures/data-source.yaml",
   218  			},
   219  			args: args{
   220  				osVer: "3.9.3",
   221  				repo: &ftypes.Repository{
   222  					Family:  ftypes.Alpine,
   223  					Release: "3.10",
   224  				},
   225  				pkgs: []ftypes.Package{
   226  					{
   227  						Name:       "jq",
   228  						Version:    "1.6-r0",
   229  						SrcVersion: "1.6-r0",
   230  					},
   231  				},
   232  			},
   233  			want: []types.DetectedVulnerability{
   234  				{
   235  					PkgName:          "jq",
   236  					VulnerabilityID:  "CVE-2020-1234",
   237  					InstalledVersion: "1.6-r0",
   238  					FixedVersion:     "1.6-r1",
   239  					DataSource: &dbTypes.DataSource{
   240  						ID:   vulnerability.Alpine,
   241  						Name: "Alpine Secdb",
   242  						URL:  "https://secdb.alpinelinux.org/",
   243  					},
   244  				},
   245  			},
   246  		},
   247  	}
   248  	for _, tt := range tests {
   249  		t.Run(tt.name, func(t *testing.T) {
   250  			_ = dbtest.InitDB(t, tt.fixtures)
   251  			defer db.Close()
   252  
   253  			s := alpine.NewScanner()
   254  			got, err := s.Detect(tt.args.osVer, tt.args.repo, tt.args.pkgs)
   255  			if tt.wantErr != "" {
   256  				require.Error(t, err)
   257  				assert.Contains(t, err.Error(), tt.wantErr)
   258  				return
   259  			}
   260  
   261  			sort.Slice(got, func(i, j int) bool {
   262  				return got[i].VulnerabilityID < got[j].VulnerabilityID
   263  			})
   264  			assert.NoError(t, err)
   265  			assert.Equal(t, tt.want, got)
   266  		})
   267  	}
   268  }
   269  
   270  func TestScanner_IsSupportedVersion(t *testing.T) {
   271  	type args struct {
   272  		osFamily ftypes.OSType
   273  		osVer    string
   274  	}
   275  	tests := []struct {
   276  		name string
   277  		now  time.Time
   278  		args args
   279  		want bool
   280  	}{
   281  		{
   282  			name: "alpine 3.6",
   283  			now:  time.Date(2019, 3, 2, 23, 59, 59, 0, time.UTC),
   284  			args: args{
   285  				osFamily: "alpine",
   286  				osVer:    "3.6",
   287  			},
   288  			want: true,
   289  		},
   290  		{
   291  			name: "alpine 3.6 with EOL",
   292  			now:  time.Date(2019, 5, 2, 23, 59, 59, 0, time.UTC),
   293  			args: args{
   294  				osFamily: "alpine",
   295  				osVer:    "3.6.5",
   296  			},
   297  			want: false,
   298  		},
   299  		{
   300  			name: "alpine 3.9",
   301  			now:  time.Date(2019, 5, 2, 23, 59, 59, 0, time.UTC),
   302  			args: args{
   303  				osFamily: "alpine",
   304  				osVer:    "3.9.0",
   305  			},
   306  			want: true,
   307  		},
   308  		{
   309  			name: "alpine 3.10",
   310  			now:  time.Date(2019, 5, 2, 23, 59, 59, 0, time.UTC),
   311  			args: args{
   312  				osFamily: "alpine",
   313  				osVer:    "3.10",
   314  			},
   315  			want: true,
   316  		},
   317  		{
   318  			name: "unknown",
   319  			now:  time.Date(2019, 5, 2, 23, 59, 59, 0, time.UTC),
   320  			args: args{
   321  				osFamily: "alpine",
   322  				osVer:    "unknown",
   323  			},
   324  			want: true,
   325  		},
   326  	}
   327  	for _, tt := range tests {
   328  		t.Run(tt.name, func(t *testing.T) {
   329  			s := alpine.NewScanner(alpine.WithClock(fake.NewFakeClock(tt.now)))
   330  			got := s.IsSupportedVersion(tt.args.osFamily, tt.args.osVer)
   331  			assert.Equal(t, tt.want, got)
   332  		})
   333  	}
   334  }