github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/fanal/artifact/image/image_test.go (about)

     1  package image_test
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"testing"
     7  	"time"
     8  
     9  	v1 "github.com/google/go-containerregistry/pkg/v1"
    10  	"github.com/stretchr/testify/assert"
    11  	"github.com/stretchr/testify/require"
    12  	"golang.org/x/xerrors"
    13  
    14  	"github.com/devseccon/trivy/pkg/fanal/analyzer"
    15  	"github.com/devseccon/trivy/pkg/fanal/artifact"
    16  	image2 "github.com/devseccon/trivy/pkg/fanal/artifact/image"
    17  	"github.com/devseccon/trivy/pkg/fanal/cache"
    18  	"github.com/devseccon/trivy/pkg/fanal/image"
    19  	"github.com/devseccon/trivy/pkg/fanal/types"
    20  
    21  	_ "github.com/devseccon/trivy/pkg/fanal/analyzer/config/all"
    22  	_ "github.com/devseccon/trivy/pkg/fanal/analyzer/imgconf/apk"
    23  	_ "github.com/devseccon/trivy/pkg/fanal/analyzer/language/php/composer"
    24  	_ "github.com/devseccon/trivy/pkg/fanal/analyzer/language/ruby/bundler"
    25  	_ "github.com/devseccon/trivy/pkg/fanal/analyzer/licensing"
    26  	_ "github.com/devseccon/trivy/pkg/fanal/analyzer/os/alpine"
    27  	_ "github.com/devseccon/trivy/pkg/fanal/analyzer/os/debian"
    28  	_ "github.com/devseccon/trivy/pkg/fanal/analyzer/pkg/apk"
    29  	_ "github.com/devseccon/trivy/pkg/fanal/analyzer/pkg/dpkg"
    30  	_ "github.com/devseccon/trivy/pkg/fanal/analyzer/repo/apk"
    31  	_ "github.com/devseccon/trivy/pkg/fanal/analyzer/secret"
    32  	_ "github.com/devseccon/trivy/pkg/fanal/handler/sysfile"
    33  )
    34  
    35  func TestArtifact_Inspect(t *testing.T) {
    36  	alpinePkgs := types.Packages{
    37  		{
    38  			ID:         "alpine-baselayout@3.2.0-r3",
    39  			Name:       "alpine-baselayout",
    40  			Version:    "3.2.0-r3",
    41  			SrcName:    "alpine-baselayout",
    42  			SrcVersion: "3.2.0-r3",
    43  			Licenses:   []string{"GPL-2.0"},
    44  			Digest:     "sha1:8f373f5b329c3aaf136eb30c63a387661ee0f3d0",
    45  			DependsOn: []string{
    46  				"busybox@1.31.1-r9",
    47  				"musl@1.1.24-r2",
    48  			},
    49  			Arch: "x86_64",
    50  			InstalledFiles: []string{
    51  				"etc/hosts",
    52  				"etc/sysctl.conf",
    53  				"etc/group",
    54  				"etc/protocols",
    55  				"etc/fstab",
    56  				"etc/mtab",
    57  				"etc/profile",
    58  				"etc/shells",
    59  				"etc/motd",
    60  				"etc/inittab",
    61  				"etc/hostname",
    62  				"etc/modules",
    63  				"etc/services",
    64  				"etc/shadow",
    65  				"etc/passwd",
    66  				"etc/profile.d/locale",
    67  				"etc/profile.d/color_prompt",
    68  				"etc/sysctl.d/00-alpine.conf",
    69  				"etc/modprobe.d/i386.conf",
    70  				"etc/modprobe.d/blacklist.conf",
    71  				"etc/modprobe.d/aliases.conf",
    72  				"etc/modprobe.d/kms.conf",
    73  				"etc/crontabs/root",
    74  				"sbin/mkmntdirs",
    75  				"var/run",
    76  				"var/spool/mail",
    77  				"var/spool/cron/crontabs",
    78  			},
    79  		},
    80  		{
    81  			ID:         "alpine-keys@2.1-r2",
    82  			Name:       "alpine-keys",
    83  			Version:    "2.1-r2",
    84  			SrcName:    "alpine-keys",
    85  			SrcVersion: "2.1-r2",
    86  			Licenses:   []string{"MIT"},
    87  			Arch:       "x86_64",
    88  			Digest:     "sha1:64929f85b7f8b4adbb664d905410312936b79d9b",
    89  			InstalledFiles: []string{
    90  				"etc/apk/keys/alpine-devel@lists.alpinelinux.org-5243ef4b.rsa.pub",
    91  				"etc/apk/keys/alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub",
    92  				"etc/apk/keys/alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub",
    93  				"usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-524d27bb.rsa.pub",
    94  				"usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-5243ef4b.rsa.pub",
    95  				"usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub",
    96  				"usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-58cbb476.rsa.pub",
    97  				"usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-58199dcc.rsa.pub",
    98  				"usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub",
    99  				"usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-58e4f17d.rsa.pub",
   100  				"usr/share/apk/keys/aarch64/alpine-devel@lists.alpinelinux.org-58199dcc.rsa.pub",
   101  				"usr/share/apk/keys/ppc64le/alpine-devel@lists.alpinelinux.org-58cbb476.rsa.pub",
   102  				"usr/share/apk/keys/x86/alpine-devel@lists.alpinelinux.org-5243ef4b.rsa.pub",
   103  				"usr/share/apk/keys/x86/alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub",
   104  				"usr/share/apk/keys/s390x/alpine-devel@lists.alpinelinux.org-58e4f17d.rsa.pub",
   105  				"usr/share/apk/keys/armhf/alpine-devel@lists.alpinelinux.org-524d27bb.rsa.pub",
   106  				"usr/share/apk/keys/x86_64/alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub",
   107  				"usr/share/apk/keys/x86_64/alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub",
   108  			},
   109  		},
   110  		{
   111  			ID:         "apk-tools@2.10.4-r3",
   112  			Name:       "apk-tools",
   113  			Version:    "2.10.4-r3",
   114  			SrcName:    "apk-tools",
   115  			SrcVersion: "2.10.4-r3",
   116  			Licenses:   []string{"GPL-2.0"},
   117  			Digest:     "sha1:b15ad0c90e4493dfdc948d6b90a8e020da8936ef",
   118  			DependsOn: []string{
   119  				"libcrypto1.1@1.1.1d-r3",
   120  				"libssl1.1@1.1.1d-r3",
   121  				"musl@1.1.24-r2",
   122  				"zlib@1.2.11-r3",
   123  			},
   124  			Arch: "x86_64",
   125  			InstalledFiles: []string{
   126  				"sbin/apk",
   127  			},
   128  		},
   129  		{
   130  			ID:         "busybox@1.31.1-r9",
   131  			Name:       "busybox",
   132  			Version:    "1.31.1-r9",
   133  			SrcName:    "busybox",
   134  			SrcVersion: "1.31.1-r9",
   135  			Licenses:   []string{"GPL-2.0"},
   136  			Digest:     "sha1:a457703d71654811ea28d8d27a5cfc49ece27b34",
   137  			DependsOn: []string{
   138  				"musl@1.1.24-r2",
   139  			},
   140  			Arch: "x86_64",
   141  			InstalledFiles: []string{
   142  				"bin/busybox",
   143  				"bin/sh",
   144  				"etc/securetty",
   145  				"etc/udhcpd.conf",
   146  				"etc/logrotate.d/acpid",
   147  				"etc/network/if-up.d/dad",
   148  				"usr/share/udhcpc/default.script",
   149  			},
   150  		},
   151  		{
   152  			ID:         "ca-certificates-cacert@20191127-r1",
   153  			Name:       "ca-certificates-cacert",
   154  			Version:    "20191127-r1",
   155  			SrcName:    "ca-certificates",
   156  			SrcVersion: "20191127-r1",
   157  			Licenses: []string{
   158  				"MPL-2.0",
   159  				"GPL-2.0",
   160  			},
   161  			Arch:   "x86_64",
   162  			Digest: "sha1:3aeb8a90d7179d2a187782e980a964494e08c5fb",
   163  			InstalledFiles: []string{
   164  				"etc/ssl/cert.pem",
   165  			},
   166  		},
   167  		{
   168  			ID:         "libc-utils@0.7.2-r0",
   169  			Name:       "libc-utils",
   170  			Version:    "0.7.2-r0",
   171  			SrcName:    "libc-dev",
   172  			SrcVersion: "0.7.2-r0",
   173  			Licenses:   []string{"BSD-3-Clause"},
   174  			Digest:     "sha1:a7bf32bd32c6d3de2d1c4d7e753a0919b998cd01",
   175  			DependsOn: []string{
   176  				"musl-utils@1.1.24-r2",
   177  			},
   178  			Arch: "x86_64",
   179  		},
   180  		{
   181  			ID:         "libcrypto1.1@1.1.1d-r3",
   182  			Name:       "libcrypto1.1",
   183  			Version:    "1.1.1d-r3",
   184  			SrcName:    "openssl",
   185  			SrcVersion: "1.1.1d-r3",
   186  			Licenses:   []string{"OpenSSL"},
   187  			Digest:     "sha1:dd8fb9a3cce7b2bcf954271da62fb85dac2b106a",
   188  			DependsOn: []string{
   189  				"musl@1.1.24-r2",
   190  			},
   191  			Arch: "x86_64",
   192  			InstalledFiles: []string{
   193  				"etc/ssl/openssl.cnf.dist",
   194  				"etc/ssl/ct_log_list.cnf",
   195  				"etc/ssl/ct_log_list.cnf.dist",
   196  				"etc/ssl/openssl.cnf",
   197  				"etc/ssl/misc/CA.pl",
   198  				"etc/ssl/misc/tsget.pl",
   199  				"etc/ssl/misc/tsget",
   200  				"lib/libcrypto.so.1.1",
   201  				"usr/lib/libcrypto.so.1.1",
   202  				"usr/lib/engines-1.1/capi.so",
   203  				"usr/lib/engines-1.1/padlock.so",
   204  				"usr/lib/engines-1.1/afalg.so",
   205  			},
   206  		},
   207  		{
   208  			ID:         "libssl1.1@1.1.1d-r3",
   209  			Name:       "libssl1.1",
   210  			Version:    "1.1.1d-r3",
   211  			SrcName:    "openssl",
   212  			SrcVersion: "1.1.1d-r3",
   213  			Licenses:   []string{"OpenSSL"},
   214  			Digest:     "sha1:938d46e41b3e56b339a3aeb2d02fad3d75728f35",
   215  			DependsOn: []string{
   216  				"libcrypto1.1@1.1.1d-r3",
   217  				"musl@1.1.24-r2",
   218  			},
   219  			Arch: "x86_64",
   220  			InstalledFiles: []string{
   221  				"lib/libssl.so.1.1",
   222  				"usr/lib/libssl.so.1.1",
   223  			},
   224  		},
   225  		{
   226  			ID:         "libtls-standalone@2.9.1-r0",
   227  			Name:       "libtls-standalone",
   228  			Version:    "2.9.1-r0",
   229  			SrcName:    "libtls-standalone",
   230  			SrcVersion: "2.9.1-r0",
   231  			Licenses:   []string{"ISC"},
   232  			Digest:     "sha1:b2e5627a56378ea6eeb962a8f33722df9393c1c5",
   233  			DependsOn: []string{
   234  				"ca-certificates-cacert@20191127-r1",
   235  				"libcrypto1.1@1.1.1d-r3",
   236  				"libssl1.1@1.1.1d-r3",
   237  				"musl@1.1.24-r2",
   238  			},
   239  			Arch: "x86_64",
   240  			InstalledFiles: []string{
   241  				"usr/lib/libtls-standalone.so.1.0.0",
   242  				"usr/lib/libtls-standalone.so.1",
   243  			},
   244  		},
   245  		{
   246  			ID:         "musl@1.1.24-r2",
   247  			Name:       "musl",
   248  			Version:    "1.1.24-r2",
   249  			SrcName:    "musl",
   250  			SrcVersion: "1.1.24-r2",
   251  			Licenses:   []string{"MIT"},
   252  			Arch:       "x86_64",
   253  			Digest:     "sha1:cb2316a189ebee5282c4a9bd98794cc2477a74c6",
   254  			InstalledFiles: []string{
   255  				"lib/libc.musl-x86_64.so.1",
   256  				"lib/ld-musl-x86_64.so.1",
   257  			},
   258  		},
   259  		{
   260  			ID:         "musl-utils@1.1.24-r2",
   261  			Name:       "musl-utils",
   262  			Version:    "1.1.24-r2",
   263  			SrcName:    "musl",
   264  			SrcVersion: "1.1.24-r2",
   265  			Licenses: []string{
   266  				"MIT",
   267  				"BSD-3-Clause",
   268  				"GPL-2.0",
   269  			},
   270  			Digest: "sha1:6d3b45e79dbab444ca7cbfa59e2833203be6fb6a",
   271  			DependsOn: []string{
   272  				"musl@1.1.24-r2",
   273  				"scanelf@1.2.4-r0",
   274  			},
   275  			Arch: "x86_64",
   276  			InstalledFiles: []string{
   277  				"sbin/ldconfig",
   278  				"usr/bin/iconv",
   279  				"usr/bin/ldd",
   280  				"usr/bin/getconf",
   281  				"usr/bin/getent",
   282  			},
   283  		},
   284  		{
   285  			ID:         "scanelf@1.2.4-r0",
   286  			Name:       "scanelf",
   287  			Version:    "1.2.4-r0",
   288  			SrcName:    "pax-utils",
   289  			SrcVersion: "1.2.4-r0",
   290  			Licenses:   []string{"GPL-2.0"},
   291  			Digest:     "sha1:d6147beb32bff803b5d9f83a3bec7ab319087185",
   292  			DependsOn: []string{
   293  				"musl@1.1.24-r2",
   294  			},
   295  			Arch: "x86_64",
   296  			InstalledFiles: []string{
   297  				"usr/bin/scanelf",
   298  			},
   299  		},
   300  		{
   301  			ID:         "ssl_client@1.31.1-r9",
   302  			Name:       "ssl_client",
   303  			Version:    "1.31.1-r9",
   304  			SrcName:    "busybox",
   305  			SrcVersion: "1.31.1-r9",
   306  			Licenses:   []string{"GPL-2.0"},
   307  			Digest:     "sha1:3b685152af320120ae8941c740d3376b54e43c10",
   308  			DependsOn: []string{
   309  				"libtls-standalone@2.9.1-r0",
   310  				"musl@1.1.24-r2",
   311  			},
   312  			Arch: "x86_64",
   313  			InstalledFiles: []string{
   314  				"usr/bin/ssl_client",
   315  			},
   316  		},
   317  		{
   318  			ID:         "zlib@1.2.11-r3",
   319  			Name:       "zlib",
   320  			Version:    "1.2.11-r3",
   321  			SrcName:    "zlib",
   322  			SrcVersion: "1.2.11-r3",
   323  			Licenses:   []string{"Zlib"},
   324  			Digest:     "sha1:acca078ee8baa93e005f57b2fae359c1efd443cd",
   325  			DependsOn: []string{
   326  				"musl@1.1.24-r2",
   327  			},
   328  			Arch: "x86_64",
   329  			InstalledFiles: []string{
   330  				"lib/libz.so.1.2.11",
   331  				"lib/libz.so.1",
   332  			},
   333  		},
   334  	}
   335  
   336  	tests := []struct {
   337  		name                    string
   338  		imagePath               string
   339  		artifactOpt             artifact.Option
   340  		missingBlobsExpectation cache.ArtifactCacheMissingBlobsExpectation
   341  		putBlobExpectations     []cache.ArtifactCachePutBlobExpectation
   342  		putArtifactExpectations []cache.ArtifactCachePutArtifactExpectation
   343  		want                    types.ArtifactReference
   344  		wantErr                 string
   345  	}{
   346  		{
   347  			name:      "happy path",
   348  			imagePath: "../../test/testdata/alpine-311.tar.gz",
   349  			artifactOpt: artifact.Option{
   350  				LicenseScannerOption: analyzer.LicenseScannerOption{Full: true},
   351  			},
   352  			missingBlobsExpectation: cache.ArtifactCacheMissingBlobsExpectation{
   353  				Args: cache.ArtifactCacheMissingBlobsArgs{
   354  					ArtifactID: "sha256:c232b7d8ac8aa08aa767313d0b53084c4380d1c01a213a5971bdb039e6538313",
   355  					BlobIDs:    []string{"sha256:0366f81c3cbeac047536f9ca133b5632544c8342544922c3ed8a3e51c0250897"},
   356  				},
   357  				Returns: cache.ArtifactCacheMissingBlobsReturns{
   358  					MissingArtifact: true,
   359  					MissingBlobIDs:  []string{"sha256:0366f81c3cbeac047536f9ca133b5632544c8342544922c3ed8a3e51c0250897"},
   360  				},
   361  			},
   362  			putBlobExpectations: []cache.ArtifactCachePutBlobExpectation{
   363  				{
   364  					Args: cache.ArtifactCachePutBlobArgs{
   365  						BlobID: "sha256:0366f81c3cbeac047536f9ca133b5632544c8342544922c3ed8a3e51c0250897",
   366  						BlobInfo: types.BlobInfo{
   367  							SchemaVersion: types.BlobJSONSchemaVersion,
   368  							Digest:        "",
   369  							DiffID:        "sha256:beee9f30bc1f711043e78d4a2be0668955d4b761d587d6f60c2c8dc081efb203",
   370  							CreatedBy:     "ADD file:0c4555f363c2672e350001f1293e689875a3760afe7b3f9146886afe67121cba in / ",
   371  							OS: types.OS{
   372  								Family: "alpine",
   373  								Name:   "3.11.5",
   374  							},
   375  							Repository: &types.Repository{
   376  								Family:  "alpine",
   377  								Release: "3.11",
   378  							},
   379  							PackageInfos: []types.PackageInfo{
   380  								{
   381  									FilePath: "lib/apk/db/installed",
   382  									Packages: alpinePkgs,
   383  								},
   384  							},
   385  							Licenses: []types.LicenseFile{
   386  								{
   387  									Type:     "header",
   388  									FilePath: "etc/ssl/misc/CA.pl",
   389  									Findings: []types.LicenseFinding{
   390  										{
   391  											Name:       "OpenSSL",
   392  											Confidence: 1,
   393  											Link:       "https://spdx.org/licenses/OpenSSL.html",
   394  										},
   395  									},
   396  								},
   397  								{
   398  									Type:     "header",
   399  									FilePath: "etc/ssl/misc/tsget.pl",
   400  									Findings: []types.LicenseFinding{
   401  										{
   402  											Name:       "OpenSSL",
   403  											Confidence: 1,
   404  											Link:       "https://spdx.org/licenses/OpenSSL.html",
   405  										},
   406  									},
   407  								},
   408  							},
   409  						},
   410  					},
   411  					Returns: cache.ArtifactCachePutBlobReturns{},
   412  				},
   413  			},
   414  			putArtifactExpectations: []cache.ArtifactCachePutArtifactExpectation{
   415  				{
   416  					Args: cache.ArtifactCachePutArtifactArgs{
   417  						ArtifactID: "sha256:c232b7d8ac8aa08aa767313d0b53084c4380d1c01a213a5971bdb039e6538313",
   418  						ArtifactInfo: types.ArtifactInfo{
   419  							SchemaVersion: types.ArtifactJSONSchemaVersion,
   420  							Architecture:  "amd64",
   421  							Created:       time.Date(2020, 3, 23, 21, 19, 34, 196162891, time.UTC),
   422  							DockerVersion: "18.09.7",
   423  							OS:            "linux",
   424  						},
   425  					},
   426  				},
   427  			},
   428  			want: types.ArtifactReference{
   429  				Name:    "../../test/testdata/alpine-311.tar.gz",
   430  				Type:    types.ArtifactContainerImage,
   431  				ID:      "sha256:c232b7d8ac8aa08aa767313d0b53084c4380d1c01a213a5971bdb039e6538313",
   432  				BlobIDs: []string{"sha256:0366f81c3cbeac047536f9ca133b5632544c8342544922c3ed8a3e51c0250897"},
   433  				ImageMetadata: types.ImageMetadata{
   434  					ID: "sha256:a187dde48cd289ac374ad8539930628314bc581a481cdb41409c9289419ddb72",
   435  					DiffIDs: []string{
   436  						"sha256:beee9f30bc1f711043e78d4a2be0668955d4b761d587d6f60c2c8dc081efb203",
   437  					},
   438  					ConfigFile: v1.ConfigFile{
   439  						Architecture:  "amd64",
   440  						Author:        "",
   441  						Container:     "fb71ddde5f6411a82eb056a9190f0cc1c80d7f77a8509ee90a2054428edb0024",
   442  						Created:       v1.Time{Time: time.Date(2020, 3, 23, 21, 19, 34, 196162891, time.UTC)},
   443  						DockerVersion: "18.09.7",
   444  						History: []v1.History{
   445  							{
   446  								Author:     "",
   447  								Created:    v1.Time{Time: time.Date(2020, 3, 23, 21, 19, 34, 27725872, time.UTC)},
   448  								CreatedBy:  "/bin/sh -c #(nop) ADD file:0c4555f363c2672e350001f1293e689875a3760afe7b3f9146886afe67121cba in / ",
   449  								Comment:    "",
   450  								EmptyLayer: false,
   451  							},
   452  							{
   453  								Author:     "",
   454  								Created:    v1.Time{Time: time.Date(2020, 3, 23, 21, 19, 34, 196162891, time.UTC)},
   455  								CreatedBy:  "/bin/sh -c #(nop)  CMD [\"/bin/sh\"]",
   456  								Comment:    "",
   457  								EmptyLayer: true,
   458  							},
   459  						},
   460  						OS: "linux",
   461  						RootFS: v1.RootFS{
   462  							Type: "layers",
   463  							DiffIDs: []v1.Hash{
   464  								{
   465  									Algorithm: "sha256",
   466  									Hex:       "beee9f30bc1f711043e78d4a2be0668955d4b761d587d6f60c2c8dc081efb203",
   467  								},
   468  							},
   469  						},
   470  						Config: v1.Config{
   471  							Cmd:         []string{"/bin/sh"},
   472  							Env:         []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"},
   473  							Hostname:    "",
   474  							Image:       "sha256:74df73bb19fbfc7fb5ab9a8234b3d98ee2fb92df5b824496679802685205ab8c",
   475  							ArgsEscaped: true,
   476  						},
   477  					},
   478  				},
   479  			},
   480  		},
   481  		{
   482  			name:      "happy path: include lock files",
   483  			imagePath: "../../test/testdata/vuln-image.tar.gz",
   484  			artifactOpt: artifact.Option{
   485  				LicenseScannerOption: analyzer.LicenseScannerOption{Full: true},
   486  			},
   487  			missingBlobsExpectation: cache.ArtifactCacheMissingBlobsExpectation{
   488  				Args: cache.ArtifactCacheMissingBlobsArgs{
   489  					ArtifactID: "sha256:33f9415ed2cd5a9cef5d5144333619745b9ec0f851f0684dd45fa79c6b26a650",
   490  					BlobIDs: []string{
   491  						"sha256:db2b5b2f26f320b80ee549495888f111151fdb44fecb2c432dfd928e96978e74",
   492  						"sha256:718d6a3d0a24966f2d9f64e0c86695d1bb896fe81df634b85300d34142c80174",
   493  						"sha256:9f6bc14198fa983fd47079bcd82df1391bee8e529a8a131a0305874eb0a51ca0",
   494  						"sha256:44264715b7132cd14cd956bf385d5f875603461f5adeafde7fdecabe2e266291",
   495  					},
   496  				},
   497  				Returns: cache.ArtifactCacheMissingBlobsReturns{
   498  					MissingBlobIDs: []string{
   499  						"sha256:db2b5b2f26f320b80ee549495888f111151fdb44fecb2c432dfd928e96978e74",
   500  						"sha256:718d6a3d0a24966f2d9f64e0c86695d1bb896fe81df634b85300d34142c80174",
   501  						"sha256:9f6bc14198fa983fd47079bcd82df1391bee8e529a8a131a0305874eb0a51ca0",
   502  						"sha256:44264715b7132cd14cd956bf385d5f875603461f5adeafde7fdecabe2e266291",
   503  					},
   504  				},
   505  			},
   506  			putBlobExpectations: []cache.ArtifactCachePutBlobExpectation{
   507  				{
   508  					Args: cache.ArtifactCachePutBlobArgs{
   509  						BlobID: "sha256:db2b5b2f26f320b80ee549495888f111151fdb44fecb2c432dfd928e96978e74",
   510  						BlobInfo: types.BlobInfo{
   511  							SchemaVersion: types.BlobJSONSchemaVersion,
   512  							Digest:        "",
   513  							DiffID:        "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
   514  							CreatedBy:     "bazel build ...",
   515  							OS: types.OS{
   516  								Family: "debian",
   517  								Name:   "9.9",
   518  							},
   519  							PackageInfos: []types.PackageInfo{
   520  								{
   521  									FilePath: "var/lib/dpkg/status.d/base",
   522  									Packages: types.Packages{
   523  										{
   524  											ID:         "base-files@9.9+deb9u9",
   525  											Name:       "base-files",
   526  											Version:    "9.9+deb9u9",
   527  											SrcName:    "base-files",
   528  											SrcVersion: "9.9+deb9u9",
   529  											Maintainer: "Santiago Vila <sanvila@debian.org>",
   530  											Arch:       "amd64",
   531  										},
   532  									},
   533  								},
   534  								{
   535  									FilePath: "var/lib/dpkg/status.d/netbase",
   536  									Packages: types.Packages{
   537  										{
   538  											ID:         "netbase@5.4",
   539  											Name:       "netbase",
   540  											Version:    "5.4",
   541  											SrcName:    "netbase",
   542  											SrcVersion: "5.4",
   543  											Maintainer: "Marco d'Itri <md@linux.it>",
   544  											Arch:       "all",
   545  										},
   546  									},
   547  								},
   548  								{
   549  									FilePath: "var/lib/dpkg/status.d/tzdata",
   550  									Packages: types.Packages{
   551  										{
   552  											ID:         "tzdata@2019a-0+deb9u1",
   553  											Name:       "tzdata",
   554  											Version:    "2019a",
   555  											SrcName:    "tzdata",
   556  											Release:    "0+deb9u1",
   557  											SrcVersion: "2019a",
   558  											SrcRelease: "0+deb9u1",
   559  											Maintainer: "GNU Libc Maintainers <debian-glibc@lists.debian.org>",
   560  											Arch:       "all",
   561  										},
   562  									},
   563  								},
   564  							},
   565  							Licenses: []types.LicenseFile{
   566  								{
   567  									Type:     types.LicenseTypeDpkg,
   568  									FilePath: "usr/share/doc/base-files/copyright",
   569  									Findings: []types.LicenseFinding{
   570  										{Name: "GPL-3.0"},
   571  									},
   572  									PkgName: "base-files",
   573  								},
   574  								{
   575  									Type:     types.LicenseTypeDpkg,
   576  									FilePath: "usr/share/doc/ca-certificates/copyright",
   577  									Findings: []types.LicenseFinding{
   578  										{Name: "GPL-2.0"},
   579  										{Name: "MPL-2.0"},
   580  									},
   581  									PkgName: "ca-certificates",
   582  								},
   583  								{
   584  									Type:     types.LicenseTypeDpkg,
   585  									FilePath: "usr/share/doc/netbase/copyright",
   586  									Findings: []types.LicenseFinding{
   587  										{Name: "GPL-2.0"},
   588  									},
   589  									PkgName: "netbase",
   590  								},
   591  							},
   592  						},
   593  					},
   594  				},
   595  				{
   596  					Args: cache.ArtifactCachePutBlobArgs{
   597  						BlobID: "sha256:718d6a3d0a24966f2d9f64e0c86695d1bb896fe81df634b85300d34142c80174",
   598  						BlobInfo: types.BlobInfo{
   599  							SchemaVersion: types.BlobJSONSchemaVersion,
   600  							Digest:        "",
   601  							DiffID:        "sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5",
   602  							CreatedBy:     "bazel build ...",
   603  							PackageInfos: []types.PackageInfo{
   604  								{
   605  									FilePath: "var/lib/dpkg/status.d/libc6",
   606  									Packages: types.Packages{
   607  										{
   608  											ID:         "libc6@2.24-11+deb9u4",
   609  											Name:       "libc6",
   610  											Version:    "2.24",
   611  											Release:    "11+deb9u4",
   612  											SrcName:    "glibc",
   613  											SrcVersion: "2.24",
   614  											SrcRelease: "11+deb9u4",
   615  											Maintainer: "GNU Libc Maintainers <debian-glibc@lists.debian.org>",
   616  											Arch:       "amd64",
   617  										},
   618  									},
   619  								},
   620  								{
   621  									FilePath: "var/lib/dpkg/status.d/libssl1",
   622  									Packages: types.Packages{
   623  										{
   624  											ID:         "libssl1.1@1.1.0k-1~deb9u1",
   625  											Name:       "libssl1.1",
   626  											Version:    "1.1.0k",
   627  											SrcName:    "openssl",
   628  											Release:    "1~deb9u1",
   629  											SrcVersion: "1.1.0k",
   630  											SrcRelease: "1~deb9u1",
   631  											Maintainer: "Debian OpenSSL Team <pkg-openssl-devel@lists.alioth.debian.org>",
   632  											Arch:       "amd64",
   633  										},
   634  									},
   635  								},
   636  								{
   637  									FilePath: "var/lib/dpkg/status.d/openssl",
   638  									Packages: types.Packages{
   639  										{
   640  											ID:         "openssl@1.1.0k-1~deb9u1",
   641  											Name:       "openssl",
   642  											Version:    "1.1.0k",
   643  											SrcName:    "openssl",
   644  											Release:    "1~deb9u1",
   645  											SrcVersion: "1.1.0k",
   646  											SrcRelease: "1~deb9u1",
   647  											Maintainer: "Debian OpenSSL Team <pkg-openssl-devel@lists.alioth.debian.org>",
   648  											Arch:       "amd64",
   649  										},
   650  									},
   651  								},
   652  							},
   653  							Licenses: []types.LicenseFile{
   654  								{
   655  									Type:     types.LicenseTypeDpkg,
   656  									FilePath: "usr/share/doc/libc6/copyright",
   657  									Findings: []types.LicenseFinding{
   658  										{Name: "LGPL-2.1"},
   659  										{Name: "GPL-2.0"},
   660  									},
   661  									PkgName: "libc6",
   662  								},
   663  								{
   664  									Type:     types.LicenseTypeDpkg,
   665  									FilePath: "usr/share/doc/libssl1.1/copyright",
   666  									Findings: []types.LicenseFinding{
   667  										{
   668  											Name:       "OpenSSL",
   669  											Confidence: 0.9960474308300395,
   670  											Link:       "https://spdx.org/licenses/OpenSSL.html",
   671  										},
   672  									},
   673  									PkgName: "libssl1.1",
   674  								},
   675  								{
   676  									Type:     types.LicenseTypeDpkg,
   677  									FilePath: "usr/share/doc/openssl/copyright",
   678  									Findings: []types.LicenseFinding{
   679  										{
   680  											Name:       "OpenSSL",
   681  											Confidence: 0.9960474308300395,
   682  											Link:       "https://spdx.org/licenses/OpenSSL.html",
   683  										},
   684  									},
   685  									PkgName: "openssl",
   686  								},
   687  							},
   688  						},
   689  					},
   690  				},
   691  				{
   692  					Args: cache.ArtifactCachePutBlobArgs{
   693  						BlobID: "sha256:9f6bc14198fa983fd47079bcd82df1391bee8e529a8a131a0305874eb0a51ca0",
   694  						BlobInfo: types.BlobInfo{
   695  							SchemaVersion: types.BlobJSONSchemaVersion,
   696  							Digest:        "",
   697  							DiffID:        "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
   698  							CreatedBy:     "COPY file:842584685f26edb24dc305d76894f51cfda2bad0c24a05e727f9d4905d184a70 in /php-app/composer.lock ",
   699  							Applications: []types.Application{
   700  								{
   701  									Type:     "composer",
   702  									FilePath: "php-app/composer.lock",
   703  									Libraries: types.Packages{
   704  										{
   705  											ID:       "guzzlehttp/guzzle@6.2.0",
   706  											Name:     "guzzlehttp/guzzle",
   707  											Version:  "6.2.0",
   708  											Licenses: []string{"MIT"},
   709  											DependsOn: []string{
   710  												"guzzlehttp/promises@v1.3.1",
   711  												"guzzlehttp/psr7@1.5.2",
   712  											},
   713  											Locations: []types.Location{
   714  												{
   715  													StartLine: 9,
   716  													EndLine:   73,
   717  												},
   718  											},
   719  										},
   720  										{
   721  											ID:       "guzzlehttp/promises@v1.3.1",
   722  											Name:     "guzzlehttp/promises",
   723  											Version:  "v1.3.1",
   724  											Licenses: []string{"MIT"},
   725  											Locations: []types.Location{
   726  												{
   727  													StartLine: 74,
   728  													EndLine:   124,
   729  												},
   730  											},
   731  										},
   732  										{
   733  											ID:       "guzzlehttp/psr7@1.5.2",
   734  											Name:     "guzzlehttp/psr7",
   735  											Version:  "1.5.2",
   736  											Licenses: []string{"MIT"},
   737  											DependsOn: []string{
   738  												"psr/http-message@1.0.1",
   739  												"ralouphie/getallheaders@2.0.5",
   740  											},
   741  											Locations: []types.Location{
   742  												{
   743  													StartLine: 125,
   744  													EndLine:   191,
   745  												},
   746  											},
   747  										},
   748  										{
   749  											ID:       "laravel/installer@v2.0.1",
   750  											Name:     "laravel/installer",
   751  											Version:  "v2.0.1",
   752  											Licenses: []string{"MIT"},
   753  											DependsOn: []string{
   754  												"guzzlehttp/guzzle@6.2.0",
   755  												"symfony/console@v4.2.7",
   756  												"symfony/filesystem@v4.2.7",
   757  												"symfony/process@v4.2.7",
   758  											},
   759  											Locations: []types.Location{
   760  												{
   761  													StartLine: 192,
   762  													EndLine:   237,
   763  												},
   764  											},
   765  										},
   766  										{
   767  											ID:        "pear/log@1.13.1",
   768  											Name:      "pear/log",
   769  											Version:   "1.13.1",
   770  											Licenses:  []string{"MIT"},
   771  											DependsOn: []string{"pear/pear_exception@v1.0.0"},
   772  											Locations: []types.Location{
   773  												{
   774  													StartLine: 238,
   775  													EndLine:   290,
   776  												},
   777  											},
   778  										},
   779  										{
   780  											ID:       "pear/pear_exception@v1.0.0",
   781  											Name:     "pear/pear_exception",
   782  											Version:  "v1.0.0",
   783  											Licenses: []string{"BSD-2-Clause"},
   784  											Locations: []types.Location{
   785  												{
   786  													StartLine: 291,
   787  													EndLine:   345,
   788  												},
   789  											},
   790  										},
   791  										{
   792  											ID:       "psr/http-message@1.0.1",
   793  											Name:     "psr/http-message",
   794  											Version:  "1.0.1",
   795  											Licenses: []string{"MIT"},
   796  											Locations: []types.Location{
   797  												{
   798  													StartLine: 346,
   799  													EndLine:   395,
   800  												},
   801  											},
   802  										},
   803  										{
   804  											ID:       "ralouphie/getallheaders@2.0.5",
   805  											Name:     "ralouphie/getallheaders",
   806  											Version:  "2.0.5",
   807  											Licenses: []string{"MIT"},
   808  											Locations: []types.Location{
   809  												{
   810  													StartLine: 396,
   811  													EndLine:   435,
   812  												},
   813  											},
   814  										},
   815  										{
   816  											ID:       "symfony/console@v4.2.7",
   817  											Name:     "symfony/console",
   818  											Version:  "v4.2.7",
   819  											Licenses: []string{"MIT"},
   820  											DependsOn: []string{
   821  												"symfony/contracts@v1.0.2",
   822  												"symfony/polyfill-mbstring@v1.11.0",
   823  											},
   824  											Locations: []types.Location{
   825  												{
   826  													StartLine: 436,
   827  													EndLine:   507,
   828  												},
   829  											},
   830  										},
   831  										{
   832  											ID:       "symfony/contracts@v1.0.2",
   833  											Name:     "symfony/contracts",
   834  											Version:  "v1.0.2",
   835  											Licenses: []string{"MIT"},
   836  											Locations: []types.Location{
   837  												{
   838  													StartLine: 508,
   839  													EndLine:   575,
   840  												},
   841  											},
   842  										},
   843  										{
   844  											ID:        "symfony/filesystem@v4.2.7",
   845  											Name:      "symfony/filesystem",
   846  											Version:   "v4.2.7",
   847  											Licenses:  []string{"MIT"},
   848  											DependsOn: []string{"symfony/polyfill-ctype@v1.11.0"},
   849  											Locations: []types.Location{
   850  												{
   851  													StartLine: 576,
   852  													EndLine:   625,
   853  												},
   854  											},
   855  										},
   856  										{
   857  											ID:       "symfony/polyfill-ctype@v1.11.0",
   858  											Name:     "symfony/polyfill-ctype",
   859  											Version:  "v1.11.0",
   860  											Licenses: []string{"MIT"},
   861  											Locations: []types.Location{
   862  												{
   863  													StartLine: 626,
   864  													EndLine:   683,
   865  												},
   866  											},
   867  										},
   868  										{
   869  											ID:       "symfony/polyfill-mbstring@v1.11.0",
   870  											Name:     "symfony/polyfill-mbstring",
   871  											Version:  "v1.11.0",
   872  											Licenses: []string{"MIT"},
   873  											Locations: []types.Location{
   874  												{
   875  													StartLine: 684,
   876  													EndLine:   742,
   877  												},
   878  											},
   879  										},
   880  										{
   881  											ID:       "symfony/process@v4.2.7",
   882  											Name:     "symfony/process",
   883  											Version:  "v4.2.7",
   884  											Licenses: []string{"MIT"},
   885  											Locations: []types.Location{
   886  												{
   887  													StartLine: 743,
   888  													EndLine:   791,
   889  												},
   890  											},
   891  										},
   892  									},
   893  								},
   894  							},
   895  							OpaqueDirs: []string{"php-app/"},
   896  						},
   897  					},
   898  				},
   899  				{
   900  					Args: cache.ArtifactCachePutBlobArgs{
   901  						BlobID: "sha256:44264715b7132cd14cd956bf385d5f875603461f5adeafde7fdecabe2e266291",
   902  						BlobInfo: types.BlobInfo{
   903  							SchemaVersion: types.BlobJSONSchemaVersion,
   904  							Digest:        "",
   905  							DiffID:        "sha256:a4595c43a874856bf95f3bfc4fbf78bbaa04c92c726276d4f64193a47ced0566",
   906  							CreatedBy:     "COPY file:c6d0373d380252b91829a5bb3c81d5b1afa574c91cef7752d18170a231c31f6d in /ruby-app/Gemfile.lock ",
   907  							Applications: []types.Application{
   908  								{
   909  									Type:     "bundler",
   910  									FilePath: "ruby-app/Gemfile.lock",
   911  									Libraries: types.Packages{
   912  										{
   913  											ID:       "actioncable@5.2.3",
   914  											Name:     "actioncable",
   915  											Version:  "5.2.3",
   916  											Indirect: true,
   917  											DependsOn: []string{
   918  												"actionpack@5.2.3",
   919  												"nio4r@2.3.1",
   920  												"websocket-driver@0.7.0",
   921  											},
   922  											Locations: []types.Location{
   923  												{
   924  													StartLine: 4,
   925  													EndLine:   4,
   926  												},
   927  											},
   928  										},
   929  										{
   930  											ID:       "actionmailer@5.2.3",
   931  											Name:     "actionmailer",
   932  											Version:  "5.2.3",
   933  											Indirect: true,
   934  											DependsOn: []string{
   935  												"actionpack@5.2.3",
   936  												"actionview@5.2.3",
   937  												"activejob@5.2.3",
   938  												"mail@2.7.1",
   939  												"rails-dom-testing@2.0.3",
   940  											},
   941  											Locations: []types.Location{
   942  												{
   943  													StartLine: 8,
   944  													EndLine:   8,
   945  												},
   946  											},
   947  										},
   948  										{
   949  											ID:       "actionpack@5.2.3",
   950  											Name:     "actionpack",
   951  											Version:  "5.2.3",
   952  											Indirect: true,
   953  											DependsOn: []string{
   954  												"actionview@5.2.3",
   955  												"activesupport@5.2.3",
   956  												"rack@2.0.7",
   957  												"rack-test@1.1.0",
   958  												"rails-dom-testing@2.0.3",
   959  												"rails-html-sanitizer@1.0.3",
   960  											},
   961  											Locations: []types.Location{
   962  												{
   963  													StartLine: 14,
   964  													EndLine:   14,
   965  												},
   966  											},
   967  										},
   968  										{
   969  											ID:       "actionview@5.2.3",
   970  											Name:     "actionview",
   971  											Version:  "5.2.3",
   972  											Indirect: true,
   973  											DependsOn: []string{
   974  												"activesupport@5.2.3",
   975  												"builder@3.2.3",
   976  												"erubi@1.8.0",
   977  												"rails-dom-testing@2.0.3",
   978  												"rails-html-sanitizer@1.0.3",
   979  											},
   980  											Locations: []types.Location{
   981  												{
   982  													StartLine: 21,
   983  													EndLine:   21,
   984  												},
   985  											},
   986  										},
   987  										{
   988  											ID:       "activejob@5.2.3",
   989  											Name:     "activejob",
   990  											Version:  "5.2.3",
   991  											Indirect: true,
   992  											DependsOn: []string{
   993  												"activesupport@5.2.3",
   994  												"globalid@0.4.2",
   995  											},
   996  											Locations: []types.Location{
   997  												{
   998  													StartLine: 27,
   999  													EndLine:   27,
  1000  												},
  1001  											},
  1002  										},
  1003  										{
  1004  											ID:        "activemodel@5.2.3",
  1005  											Name:      "activemodel",
  1006  											Version:   "5.2.3",
  1007  											Indirect:  true,
  1008  											DependsOn: []string{"activesupport@5.2.3"},
  1009  											Locations: []types.Location{
  1010  												{
  1011  													StartLine: 30,
  1012  													EndLine:   30,
  1013  												},
  1014  											},
  1015  										},
  1016  										{
  1017  											ID:       "activerecord@5.2.3",
  1018  											Name:     "activerecord",
  1019  											Version:  "5.2.3",
  1020  											Indirect: true,
  1021  											DependsOn: []string{
  1022  												"activemodel@5.2.3",
  1023  												"activesupport@5.2.3",
  1024  												"arel@9.0.0",
  1025  											},
  1026  											Locations: []types.Location{
  1027  												{
  1028  													StartLine: 32,
  1029  													EndLine:   32,
  1030  												},
  1031  											},
  1032  										},
  1033  										{
  1034  											ID:       "activestorage@5.2.3",
  1035  											Name:     "activestorage",
  1036  											Version:  "5.2.3",
  1037  											Indirect: true,
  1038  											DependsOn: []string{
  1039  												"actionpack@5.2.3",
  1040  												"activerecord@5.2.3",
  1041  												"marcel@0.3.3",
  1042  											},
  1043  											Locations: []types.Location{
  1044  												{
  1045  													StartLine: 36,
  1046  													EndLine:   36,
  1047  												},
  1048  											},
  1049  										},
  1050  										{
  1051  											ID:       "activesupport@5.2.3",
  1052  											Name:     "activesupport",
  1053  											Version:  "5.2.3",
  1054  											Indirect: true,
  1055  											DependsOn: []string{
  1056  												"concurrent-ruby@1.1.5",
  1057  												"i18n@1.6.0",
  1058  												"minitest@5.11.3",
  1059  												"tzinfo@1.2.5",
  1060  											},
  1061  											Locations: []types.Location{
  1062  												{
  1063  													StartLine: 40,
  1064  													EndLine:   40,
  1065  												},
  1066  											},
  1067  										},
  1068  										{
  1069  											ID:        "arel@9.0.0",
  1070  											Name:      "arel",
  1071  											Version:   "9.0.0",
  1072  											Indirect:  true,
  1073  											DependsOn: []string(nil),
  1074  											Locations: []types.Location{
  1075  												{
  1076  													StartLine: 45,
  1077  													EndLine:   45,
  1078  												},
  1079  											},
  1080  										},
  1081  										{
  1082  											ID:        "ast@2.4.0",
  1083  											Name:      "ast",
  1084  											Version:   "2.4.0",
  1085  											Indirect:  true,
  1086  											DependsOn: []string(nil),
  1087  											Locations: []types.Location{
  1088  												{
  1089  													StartLine: 46,
  1090  													EndLine:   46,
  1091  												},
  1092  											},
  1093  										},
  1094  										{
  1095  											ID:        "builder@3.2.3",
  1096  											Name:      "builder",
  1097  											Version:   "3.2.3",
  1098  											Indirect:  true,
  1099  											DependsOn: []string(nil),
  1100  											Locations: []types.Location{
  1101  												{
  1102  													StartLine: 47,
  1103  													EndLine:   47,
  1104  												},
  1105  											},
  1106  										},
  1107  										{
  1108  											ID:        "coderay@1.1.2",
  1109  											Name:      "coderay",
  1110  											Version:   "1.1.2",
  1111  											Indirect:  true,
  1112  											DependsOn: []string(nil),
  1113  											Locations: []types.Location{
  1114  												{
  1115  													StartLine: 48,
  1116  													EndLine:   48,
  1117  												},
  1118  											},
  1119  										},
  1120  										{
  1121  											ID:        "concurrent-ruby@1.1.5",
  1122  											Name:      "concurrent-ruby",
  1123  											Version:   "1.1.5",
  1124  											Indirect:  true,
  1125  											DependsOn: []string(nil),
  1126  											Locations: []types.Location{
  1127  												{
  1128  													StartLine: 49,
  1129  													EndLine:   49,
  1130  												},
  1131  											},
  1132  										},
  1133  										{
  1134  											ID:        "crass@1.0.4",
  1135  											Name:      "crass",
  1136  											Version:   "1.0.4",
  1137  											Indirect:  true,
  1138  											DependsOn: []string(nil),
  1139  											Locations: []types.Location{
  1140  												{
  1141  													StartLine: 50,
  1142  													EndLine:   50,
  1143  												},
  1144  											},
  1145  										},
  1146  										{
  1147  											ID:        "dotenv@2.7.2",
  1148  											Name:      "dotenv",
  1149  											Version:   "2.7.2",
  1150  											Indirect:  false,
  1151  											DependsOn: []string(nil),
  1152  											Locations: []types.Location{
  1153  												{
  1154  													StartLine: 51,
  1155  													EndLine:   51,
  1156  												},
  1157  											},
  1158  										},
  1159  										{
  1160  											ID:        "erubi@1.8.0",
  1161  											Name:      "erubi",
  1162  											Version:   "1.8.0",
  1163  											Indirect:  true,
  1164  											DependsOn: []string(nil),
  1165  											Locations: []types.Location{
  1166  												{
  1167  													StartLine: 52,
  1168  													EndLine:   52,
  1169  												},
  1170  											},
  1171  										},
  1172  										{
  1173  											ID:        "faker@1.9.3",
  1174  											Name:      "faker",
  1175  											Version:   "1.9.3",
  1176  											Indirect:  false,
  1177  											DependsOn: []string{"i18n@1.6.0"},
  1178  											Locations: []types.Location{
  1179  												{
  1180  													StartLine: 53,
  1181  													EndLine:   53,
  1182  												},
  1183  											},
  1184  										},
  1185  										{
  1186  											ID:        "globalid@0.4.2",
  1187  											Name:      "globalid",
  1188  											Version:   "0.4.2",
  1189  											Indirect:  true,
  1190  											DependsOn: []string{"activesupport@5.2.3"},
  1191  											Locations: []types.Location{
  1192  												{
  1193  													StartLine: 55,
  1194  													EndLine:   55,
  1195  												},
  1196  											},
  1197  										},
  1198  										{
  1199  											ID:        "i18n@1.6.0",
  1200  											Name:      "i18n",
  1201  											Version:   "1.6.0",
  1202  											Indirect:  true,
  1203  											DependsOn: []string{"concurrent-ruby@1.1.5"},
  1204  											Locations: []types.Location{
  1205  												{
  1206  													StartLine: 57,
  1207  													EndLine:   57,
  1208  												},
  1209  											},
  1210  										},
  1211  										{
  1212  											ID:        "jaro_winkler@1.5.2",
  1213  											Name:      "jaro_winkler",
  1214  											Version:   "1.5.2",
  1215  											Indirect:  true,
  1216  											DependsOn: []string(nil),
  1217  											Locations: []types.Location{
  1218  												{
  1219  													StartLine: 59,
  1220  													EndLine:   59,
  1221  												},
  1222  											},
  1223  										},
  1224  										{
  1225  											ID:        "json@2.2.0",
  1226  											Name:      "json",
  1227  											Version:   "2.2.0",
  1228  											Indirect:  false,
  1229  											DependsOn: []string(nil),
  1230  											Locations: []types.Location{
  1231  												{
  1232  													StartLine: 60,
  1233  													EndLine:   60,
  1234  												},
  1235  											},
  1236  										},
  1237  										{
  1238  											ID:       "loofah@2.2.3",
  1239  											Name:     "loofah",
  1240  											Version:  "2.2.3",
  1241  											Indirect: true,
  1242  											DependsOn: []string{
  1243  												"crass@1.0.4",
  1244  												"nokogiri@1.10.3",
  1245  											},
  1246  											Locations: []types.Location{
  1247  												{
  1248  													StartLine: 61,
  1249  													EndLine:   61,
  1250  												},
  1251  											},
  1252  										},
  1253  										{
  1254  											ID:        "mail@2.7.1",
  1255  											Name:      "mail",
  1256  											Version:   "2.7.1",
  1257  											Indirect:  true,
  1258  											DependsOn: []string{"mini_mime@1.0.1"},
  1259  											Locations: []types.Location{
  1260  												{
  1261  													StartLine: 64,
  1262  													EndLine:   64,
  1263  												},
  1264  											},
  1265  										},
  1266  										{
  1267  											ID:        "marcel@0.3.3",
  1268  											Name:      "marcel",
  1269  											Version:   "0.3.3",
  1270  											Indirect:  true,
  1271  											DependsOn: []string{"mimemagic@0.3.3"},
  1272  											Locations: []types.Location{
  1273  												{
  1274  													StartLine: 66,
  1275  													EndLine:   66,
  1276  												},
  1277  											},
  1278  										},
  1279  										{
  1280  											ID:        "method_source@0.9.2",
  1281  											Name:      "method_source",
  1282  											Version:   "0.9.2",
  1283  											Indirect:  true,
  1284  											DependsOn: []string(nil),
  1285  											Locations: []types.Location{
  1286  												{
  1287  													StartLine: 68,
  1288  													EndLine:   68,
  1289  												},
  1290  											},
  1291  										},
  1292  										{
  1293  											ID:        "mimemagic@0.3.3",
  1294  											Name:      "mimemagic",
  1295  											Version:   "0.3.3",
  1296  											Indirect:  true,
  1297  											DependsOn: []string(nil),
  1298  											Locations: []types.Location{
  1299  												{
  1300  													StartLine: 69,
  1301  													EndLine:   69,
  1302  												},
  1303  											},
  1304  										},
  1305  										{
  1306  											ID:        "mini_mime@1.0.1",
  1307  											Name:      "mini_mime",
  1308  											Version:   "1.0.1",
  1309  											Indirect:  true,
  1310  											DependsOn: []string(nil),
  1311  											Locations: []types.Location{
  1312  												{
  1313  													StartLine: 70,
  1314  													EndLine:   70,
  1315  												},
  1316  											},
  1317  										},
  1318  										{
  1319  											ID:        "mini_portile2@2.4.0",
  1320  											Name:      "mini_portile2",
  1321  											Version:   "2.4.0",
  1322  											Indirect:  true,
  1323  											DependsOn: []string(nil),
  1324  											Locations: []types.Location{
  1325  												{
  1326  													StartLine: 71,
  1327  													EndLine:   71,
  1328  												},
  1329  											},
  1330  										},
  1331  										{
  1332  											ID:        "minitest@5.11.3",
  1333  											Name:      "minitest",
  1334  											Version:   "5.11.3",
  1335  											Indirect:  true,
  1336  											DependsOn: []string(nil),
  1337  											Locations: []types.Location{
  1338  												{
  1339  													StartLine: 72,
  1340  													EndLine:   72,
  1341  												},
  1342  											},
  1343  										},
  1344  										{
  1345  											ID:        "nio4r@2.3.1",
  1346  											Name:      "nio4r",
  1347  											Version:   "2.3.1",
  1348  											Indirect:  true,
  1349  											DependsOn: []string(nil),
  1350  											Locations: []types.Location{
  1351  												{
  1352  													StartLine: 73,
  1353  													EndLine:   73,
  1354  												},
  1355  											},
  1356  										},
  1357  										{
  1358  											ID:        "nokogiri@1.10.3",
  1359  											Name:      "nokogiri",
  1360  											Version:   "1.10.3",
  1361  											Indirect:  true,
  1362  											DependsOn: []string{"mini_portile2@2.4.0"},
  1363  											Locations: []types.Location{
  1364  												{
  1365  													StartLine: 74,
  1366  													EndLine:   74,
  1367  												},
  1368  											},
  1369  										},
  1370  										{
  1371  											ID:        "parallel@1.17.0",
  1372  											Name:      "parallel",
  1373  											Version:   "1.17.0",
  1374  											Indirect:  true,
  1375  											DependsOn: []string(nil),
  1376  											Locations: []types.Location{
  1377  												{
  1378  													StartLine: 76,
  1379  													EndLine:   76,
  1380  												},
  1381  											},
  1382  										},
  1383  										{
  1384  											ID:        "parser@2.6.3.0",
  1385  											Name:      "parser",
  1386  											Version:   "2.6.3.0",
  1387  											Indirect:  true,
  1388  											DependsOn: []string{"ast@2.4.0"},
  1389  											Locations: []types.Location{
  1390  												{
  1391  													StartLine: 77,
  1392  													EndLine:   77,
  1393  												},
  1394  											},
  1395  										},
  1396  										{
  1397  											ID:       "pry@0.12.2",
  1398  											Name:     "pry",
  1399  											Version:  "0.12.2",
  1400  											Indirect: false,
  1401  											DependsOn: []string{
  1402  												"coderay@1.1.2",
  1403  												"method_source@0.9.2",
  1404  											},
  1405  											Locations: []types.Location{
  1406  												{
  1407  													StartLine: 79,
  1408  													EndLine:   79,
  1409  												},
  1410  											},
  1411  										},
  1412  										{
  1413  											ID:        "psych@3.1.0",
  1414  											Name:      "psych",
  1415  											Version:   "3.1.0",
  1416  											Indirect:  true,
  1417  											DependsOn: []string(nil),
  1418  											Locations: []types.Location{
  1419  												{
  1420  													StartLine: 82,
  1421  													EndLine:   82,
  1422  												},
  1423  											},
  1424  										},
  1425  										{
  1426  											ID:        "rack@2.0.7",
  1427  											Name:      "rack",
  1428  											Version:   "2.0.7",
  1429  											Indirect:  true,
  1430  											DependsOn: []string(nil),
  1431  											Locations: []types.Location{
  1432  												{
  1433  													StartLine: 83,
  1434  													EndLine:   83,
  1435  												},
  1436  											},
  1437  										},
  1438  										{
  1439  											ID:        "rack-test@1.1.0",
  1440  											Name:      "rack-test",
  1441  											Version:   "1.1.0",
  1442  											Indirect:  true,
  1443  											DependsOn: []string{"rack@2.0.7"},
  1444  											Locations: []types.Location{
  1445  												{
  1446  													StartLine: 84,
  1447  													EndLine:   84,
  1448  												},
  1449  											},
  1450  										},
  1451  										{
  1452  											ID:       "rails@5.2.0",
  1453  											Name:     "rails",
  1454  											Version:  "5.2.0",
  1455  											Indirect: false,
  1456  											DependsOn: []string{
  1457  												"actioncable@5.2.3",
  1458  												"actionmailer@5.2.3",
  1459  												"actionpack@5.2.3",
  1460  												"actionview@5.2.3",
  1461  												"activejob@5.2.3",
  1462  												"activemodel@5.2.3",
  1463  												"activerecord@5.2.3",
  1464  												"activestorage@5.2.3",
  1465  												"activesupport@5.2.3",
  1466  												"railties@5.2.3",
  1467  												"sprockets-rails@3.2.1",
  1468  											},
  1469  											Locations: []types.Location{
  1470  												{
  1471  													StartLine: 86,
  1472  													EndLine:   86,
  1473  												},
  1474  											},
  1475  										},
  1476  										{
  1477  											ID:       "rails-dom-testing@2.0.3",
  1478  											Name:     "rails-dom-testing",
  1479  											Version:  "2.0.3",
  1480  											Indirect: true,
  1481  											DependsOn: []string{
  1482  												"activesupport@5.2.3",
  1483  												"nokogiri@1.10.3",
  1484  											},
  1485  											Locations: []types.Location{
  1486  												{
  1487  													StartLine: 99,
  1488  													EndLine:   99,
  1489  												},
  1490  											},
  1491  										},
  1492  										{
  1493  											ID:        "rails-html-sanitizer@1.0.3",
  1494  											Name:      "rails-html-sanitizer",
  1495  											Version:   "1.0.3",
  1496  											Indirect:  true,
  1497  											DependsOn: []string{"loofah@2.2.3"},
  1498  											Locations: []types.Location{
  1499  												{
  1500  													StartLine: 102,
  1501  													EndLine:   102,
  1502  												},
  1503  											},
  1504  										},
  1505  										{
  1506  											ID:       "railties@5.2.3",
  1507  											Name:     "railties",
  1508  											Version:  "5.2.3",
  1509  											Indirect: true,
  1510  											DependsOn: []string{
  1511  												"actionpack@5.2.3",
  1512  												"activesupport@5.2.3",
  1513  												"method_source@0.9.2",
  1514  												"rake@12.3.2",
  1515  												"thor@0.20.3",
  1516  											},
  1517  											Locations: []types.Location{
  1518  												{
  1519  													StartLine: 104,
  1520  													EndLine:   104,
  1521  												},
  1522  											},
  1523  										},
  1524  										{
  1525  											ID:        "rainbow@3.0.0",
  1526  											Name:      "rainbow",
  1527  											Version:   "3.0.0",
  1528  											Indirect:  true,
  1529  											DependsOn: []string(nil),
  1530  											Locations: []types.Location{
  1531  												{
  1532  													StartLine: 110,
  1533  													EndLine:   110,
  1534  												},
  1535  											},
  1536  										},
  1537  										{
  1538  											ID:        "rake@12.3.2",
  1539  											Name:      "rake",
  1540  											Version:   "12.3.2",
  1541  											Indirect:  true,
  1542  											DependsOn: []string(nil),
  1543  											Locations: []types.Location{
  1544  												{
  1545  													StartLine: 111,
  1546  													EndLine:   111,
  1547  												},
  1548  											},
  1549  										},
  1550  										{
  1551  											ID:       "rubocop@0.67.2",
  1552  											Name:     "rubocop",
  1553  											Version:  "0.67.2",
  1554  											Indirect: false,
  1555  											DependsOn: []string{
  1556  												"jaro_winkler@1.5.2",
  1557  												"parallel@1.17.0",
  1558  												"parser@2.6.3.0",
  1559  												"psych@3.1.0",
  1560  												"rainbow@3.0.0",
  1561  												"ruby-progressbar@1.10.0",
  1562  												"unicode-display_width@1.5.0",
  1563  											},
  1564  											Locations: []types.Location{
  1565  												{
  1566  													StartLine: 112,
  1567  													EndLine:   112,
  1568  												},
  1569  											},
  1570  										},
  1571  										{
  1572  											ID:        "ruby-progressbar@1.10.0",
  1573  											Name:      "ruby-progressbar",
  1574  											Version:   "1.10.0",
  1575  											Indirect:  true,
  1576  											DependsOn: []string(nil),
  1577  											Locations: []types.Location{
  1578  												{
  1579  													StartLine: 120,
  1580  													EndLine:   120,
  1581  												},
  1582  											},
  1583  										},
  1584  										{
  1585  											ID:       "sprockets@3.7.2",
  1586  											Name:     "sprockets",
  1587  											Version:  "3.7.2",
  1588  											Indirect: true,
  1589  											DependsOn: []string{
  1590  												"concurrent-ruby@1.1.5",
  1591  												"rack@2.0.7",
  1592  											},
  1593  											Locations: []types.Location{
  1594  												{
  1595  													StartLine: 121,
  1596  													EndLine:   121,
  1597  												},
  1598  											},
  1599  										},
  1600  										{
  1601  											ID:       "sprockets-rails@3.2.1",
  1602  											Name:     "sprockets-rails",
  1603  											Version:  "3.2.1",
  1604  											Indirect: true,
  1605  											DependsOn: []string{
  1606  												"actionpack@5.2.3",
  1607  												"activesupport@5.2.3",
  1608  												"sprockets@3.7.2",
  1609  											},
  1610  											Locations: []types.Location{
  1611  												{
  1612  													StartLine: 124,
  1613  													EndLine:   124,
  1614  												},
  1615  											},
  1616  										},
  1617  										{
  1618  											ID:        "thor@0.20.3",
  1619  											Name:      "thor",
  1620  											Version:   "0.20.3",
  1621  											Indirect:  true,
  1622  											DependsOn: []string(nil),
  1623  											Locations: []types.Location{
  1624  												{
  1625  													StartLine: 128,
  1626  													EndLine:   128,
  1627  												},
  1628  											},
  1629  										},
  1630  										{
  1631  											ID:        "thread_safe@0.3.6",
  1632  											Name:      "thread_safe",
  1633  											Version:   "0.3.6",
  1634  											Indirect:  true,
  1635  											DependsOn: []string(nil),
  1636  											Locations: []types.Location{
  1637  												{
  1638  													StartLine: 129,
  1639  													EndLine:   129,
  1640  												},
  1641  											},
  1642  										},
  1643  										{
  1644  											ID:        "tzinfo@1.2.5",
  1645  											Name:      "tzinfo",
  1646  											Version:   "1.2.5",
  1647  											Indirect:  true,
  1648  											DependsOn: []string{"thread_safe@0.3.6"},
  1649  											Locations: []types.Location{
  1650  												{
  1651  													StartLine: 130,
  1652  													EndLine:   130,
  1653  												},
  1654  											},
  1655  										},
  1656  										{
  1657  											ID:        "unicode-display_width@1.5.0",
  1658  											Name:      "unicode-display_width",
  1659  											Version:   "1.5.0",
  1660  											Indirect:  true,
  1661  											DependsOn: []string(nil),
  1662  											Locations: []types.Location{
  1663  												{
  1664  													StartLine: 132,
  1665  													EndLine:   132,
  1666  												},
  1667  											},
  1668  										},
  1669  										{
  1670  											ID:        "websocket-driver@0.7.0",
  1671  											Name:      "websocket-driver",
  1672  											Version:   "0.7.0",
  1673  											Indirect:  true,
  1674  											DependsOn: []string{"websocket-extensions@0.1.3"},
  1675  											Locations: []types.Location{
  1676  												{
  1677  													StartLine: 133,
  1678  													EndLine:   133,
  1679  												},
  1680  											},
  1681  										},
  1682  										{
  1683  											ID:        "websocket-extensions@0.1.3",
  1684  											Name:      "websocket-extensions",
  1685  											Version:   "0.1.3",
  1686  											Indirect:  true,
  1687  											DependsOn: []string(nil),
  1688  											Locations: []types.Location{
  1689  												{
  1690  													StartLine: 135,
  1691  													EndLine:   135,
  1692  												},
  1693  											},
  1694  										},
  1695  									},
  1696  								},
  1697  							},
  1698  							OpaqueDirs: []string{
  1699  								"ruby-app/",
  1700  							},
  1701  						},
  1702  					},
  1703  				},
  1704  			},
  1705  			want: types.ArtifactReference{
  1706  				Name: "../../test/testdata/vuln-image.tar.gz",
  1707  				Type: types.ArtifactContainerImage,
  1708  				ID:   "sha256:33f9415ed2cd5a9cef5d5144333619745b9ec0f851f0684dd45fa79c6b26a650",
  1709  				BlobIDs: []string{
  1710  					"sha256:db2b5b2f26f320b80ee549495888f111151fdb44fecb2c432dfd928e96978e74",
  1711  					"sha256:718d6a3d0a24966f2d9f64e0c86695d1bb896fe81df634b85300d34142c80174",
  1712  					"sha256:9f6bc14198fa983fd47079bcd82df1391bee8e529a8a131a0305874eb0a51ca0",
  1713  					"sha256:44264715b7132cd14cd956bf385d5f875603461f5adeafde7fdecabe2e266291",
  1714  				},
  1715  				ImageMetadata: types.ImageMetadata{
  1716  					ID: "sha256:58701fd185bda36cab0557bb6438661831267aa4a9e0b54211c4d5317a48aff4",
  1717  					DiffIDs: []string{
  1718  						"sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
  1719  						"sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5",
  1720  						"sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
  1721  						"sha256:a4595c43a874856bf95f3bfc4fbf78bbaa04c92c726276d4f64193a47ced0566",
  1722  					},
  1723  					ConfigFile: v1.ConfigFile{
  1724  						Architecture:  "amd64",
  1725  						Author:        "",
  1726  						Created:       v1.Time{Time: time.Date(2020, 2, 16, 10, 38, 41, 114114788, time.UTC)},
  1727  						DockerVersion: "19.03.5",
  1728  						History: []v1.History{
  1729  							{
  1730  								Author:     "Bazel",
  1731  								Created:    v1.Time{Time: time.Date(1970, 01, 01, 0, 0, 0, 0, time.UTC)},
  1732  								CreatedBy:  "bazel build ...",
  1733  								EmptyLayer: false,
  1734  							},
  1735  							{
  1736  								Author:     "Bazel",
  1737  								Created:    v1.Time{Time: time.Date(1970, 01, 01, 0, 0, 0, 0, time.UTC)},
  1738  								CreatedBy:  "bazel build ...",
  1739  								EmptyLayer: false,
  1740  							},
  1741  							{
  1742  								Author:     "",
  1743  								Created:    v1.Time{Time: time.Date(2020, 2, 16, 10, 38, 40, 976530082, time.UTC)},
  1744  								CreatedBy:  "/bin/sh -c #(nop) COPY file:842584685f26edb24dc305d76894f51cfda2bad0c24a05e727f9d4905d184a70 in /php-app/composer.lock ",
  1745  								Comment:    "",
  1746  								EmptyLayer: false,
  1747  							},
  1748  							{
  1749  								Author:     "",
  1750  								Created:    v1.Time{Time: time.Date(2020, 2, 16, 10, 38, 41, 114114788, time.UTC)},
  1751  								CreatedBy:  "/bin/sh -c #(nop) COPY file:c6d0373d380252b91829a5bb3c81d5b1afa574c91cef7752d18170a231c31f6d in /ruby-app/Gemfile.lock ",
  1752  								Comment:    "",
  1753  								EmptyLayer: false,
  1754  							},
  1755  						},
  1756  						OS: "linux",
  1757  						RootFS: v1.RootFS{
  1758  							Type: "layers",
  1759  							DiffIDs: []v1.Hash{
  1760  								{
  1761  									Algorithm: "sha256",
  1762  									Hex:       "932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
  1763  								},
  1764  								{
  1765  									Algorithm: "sha256",
  1766  									Hex:       "dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5",
  1767  								},
  1768  								{
  1769  									Algorithm: "sha256",
  1770  									Hex:       "24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
  1771  								},
  1772  								{
  1773  									Algorithm: "sha256",
  1774  									Hex:       "a4595c43a874856bf95f3bfc4fbf78bbaa04c92c726276d4f64193a47ced0566",
  1775  								},
  1776  							},
  1777  						},
  1778  						Config: v1.Config{
  1779  							Env: []string{
  1780  								"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
  1781  								"SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt",
  1782  							},
  1783  							Image: "sha256:916390dcf84a1c7852e298f24fb5389a6e7801102086924e55eb08cd58d6a741",
  1784  						},
  1785  					},
  1786  				},
  1787  			},
  1788  		},
  1789  		{
  1790  			name:      "happy path: disable analyzers",
  1791  			imagePath: "../../test/testdata/vuln-image.tar.gz",
  1792  			artifactOpt: artifact.Option{
  1793  				DisabledAnalyzers: []analyzer.Type{
  1794  					analyzer.TypeDebian,
  1795  					analyzer.TypeDpkg,
  1796  					analyzer.TypeDpkgLicense,
  1797  					analyzer.TypeComposer,
  1798  					analyzer.TypeBundler,
  1799  					analyzer.TypeLicenseFile,
  1800  				},
  1801  				LicenseScannerOption: analyzer.LicenseScannerOption{Full: true},
  1802  			},
  1803  			missingBlobsExpectation: cache.ArtifactCacheMissingBlobsExpectation{
  1804  				Args: cache.ArtifactCacheMissingBlobsArgs{
  1805  					ArtifactID: "sha256:33f9415ed2cd5a9cef5d5144333619745b9ec0f851f0684dd45fa79c6b26a650",
  1806  					BlobIDs: []string{
  1807  						"sha256:dc2c102de2a4dc82bc017564a2c1a46646f071367bd51d3ddd80171dc5a78ffe",
  1808  						"sha256:e6bc45e7459162f5a27dd7bd310a420f27378f2ea24c6ed5f0a083f2377bde24",
  1809  						"sha256:8184bee7b1985e0abd72288946c246b90e1847b36fdcd50ca3d588b9371ec920",
  1810  						"sha256:f1bb0ccf476528c6165a2f1a74d0e5a0cb06c9b254a0def6b1183db662e83dd4",
  1811  					},
  1812  				},
  1813  				Returns: cache.ArtifactCacheMissingBlobsReturns{
  1814  					MissingBlobIDs: []string{
  1815  						"sha256:dc2c102de2a4dc82bc017564a2c1a46646f071367bd51d3ddd80171dc5a78ffe",
  1816  						"sha256:e6bc45e7459162f5a27dd7bd310a420f27378f2ea24c6ed5f0a083f2377bde24",
  1817  						"sha256:8184bee7b1985e0abd72288946c246b90e1847b36fdcd50ca3d588b9371ec920",
  1818  						"sha256:f1bb0ccf476528c6165a2f1a74d0e5a0cb06c9b254a0def6b1183db662e83dd4",
  1819  					},
  1820  				},
  1821  			},
  1822  			putBlobExpectations: []cache.ArtifactCachePutBlobExpectation{
  1823  				{
  1824  					Args: cache.ArtifactCachePutBlobArgs{
  1825  						BlobID: "sha256:dc2c102de2a4dc82bc017564a2c1a46646f071367bd51d3ddd80171dc5a78ffe",
  1826  						BlobInfo: types.BlobInfo{
  1827  							SchemaVersion: types.BlobJSONSchemaVersion,
  1828  							Digest:        "",
  1829  							DiffID:        "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
  1830  							CreatedBy:     "bazel build ...",
  1831  						},
  1832  					},
  1833  				},
  1834  				{
  1835  					Args: cache.ArtifactCachePutBlobArgs{
  1836  						BlobID: "sha256:e6bc45e7459162f5a27dd7bd310a420f27378f2ea24c6ed5f0a083f2377bde24",
  1837  						BlobInfo: types.BlobInfo{
  1838  							SchemaVersion: types.BlobJSONSchemaVersion,
  1839  							Digest:        "",
  1840  							DiffID:        "sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5",
  1841  							CreatedBy:     "bazel build ...",
  1842  						},
  1843  					},
  1844  				},
  1845  				{
  1846  					Args: cache.ArtifactCachePutBlobArgs{
  1847  						BlobID: "sha256:8184bee7b1985e0abd72288946c246b90e1847b36fdcd50ca3d588b9371ec920",
  1848  						BlobInfo: types.BlobInfo{
  1849  							SchemaVersion: types.BlobJSONSchemaVersion,
  1850  							Digest:        "",
  1851  							DiffID:        "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
  1852  							CreatedBy:     "COPY file:842584685f26edb24dc305d76894f51cfda2bad0c24a05e727f9d4905d184a70 in /php-app/composer.lock ",
  1853  							OpaqueDirs:    []string{"php-app/"},
  1854  						},
  1855  					},
  1856  				},
  1857  				{
  1858  					Args: cache.ArtifactCachePutBlobArgs{
  1859  						BlobID: "sha256:f1bb0ccf476528c6165a2f1a74d0e5a0cb06c9b254a0def6b1183db662e83dd4",
  1860  						BlobInfo: types.BlobInfo{
  1861  							SchemaVersion: types.BlobJSONSchemaVersion,
  1862  							Digest:        "",
  1863  							DiffID:        "sha256:a4595c43a874856bf95f3bfc4fbf78bbaa04c92c726276d4f64193a47ced0566",
  1864  							CreatedBy:     "COPY file:c6d0373d380252b91829a5bb3c81d5b1afa574c91cef7752d18170a231c31f6d in /ruby-app/Gemfile.lock ",
  1865  							OpaqueDirs:    []string{"ruby-app/"},
  1866  						},
  1867  					},
  1868  				},
  1869  			},
  1870  			want: types.ArtifactReference{
  1871  				Name: "../../test/testdata/vuln-image.tar.gz",
  1872  				Type: types.ArtifactContainerImage,
  1873  				ID:   "sha256:33f9415ed2cd5a9cef5d5144333619745b9ec0f851f0684dd45fa79c6b26a650",
  1874  				BlobIDs: []string{
  1875  					"sha256:dc2c102de2a4dc82bc017564a2c1a46646f071367bd51d3ddd80171dc5a78ffe",
  1876  					"sha256:e6bc45e7459162f5a27dd7bd310a420f27378f2ea24c6ed5f0a083f2377bde24",
  1877  					"sha256:8184bee7b1985e0abd72288946c246b90e1847b36fdcd50ca3d588b9371ec920",
  1878  					"sha256:f1bb0ccf476528c6165a2f1a74d0e5a0cb06c9b254a0def6b1183db662e83dd4",
  1879  				},
  1880  				ImageMetadata: types.ImageMetadata{
  1881  					ID: "sha256:58701fd185bda36cab0557bb6438661831267aa4a9e0b54211c4d5317a48aff4",
  1882  					DiffIDs: []string{
  1883  						"sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
  1884  						"sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5",
  1885  						"sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
  1886  						"sha256:a4595c43a874856bf95f3bfc4fbf78bbaa04c92c726276d4f64193a47ced0566",
  1887  					},
  1888  					ConfigFile: v1.ConfigFile{
  1889  						Architecture:  "amd64",
  1890  						Author:        "",
  1891  						Created:       v1.Time{Time: time.Date(2020, 2, 16, 10, 38, 41, 114114788, time.UTC)},
  1892  						DockerVersion: "19.03.5",
  1893  						History: []v1.History{
  1894  							{
  1895  								Author:     "Bazel",
  1896  								Created:    v1.Time{Time: time.Date(1970, 01, 01, 0, 0, 0, 0, time.UTC)},
  1897  								CreatedBy:  "bazel build ...",
  1898  								Comment:    "",
  1899  								EmptyLayer: false,
  1900  							},
  1901  							{
  1902  								Author:     "Bazel",
  1903  								Created:    v1.Time{Time: time.Date(1970, 01, 01, 0, 0, 0, 0, time.UTC)},
  1904  								CreatedBy:  "bazel build ...",
  1905  								Comment:    "",
  1906  								EmptyLayer: false,
  1907  							},
  1908  							{
  1909  								Created:    v1.Time{Time: time.Date(2020, 2, 16, 10, 38, 40, 976530082, time.UTC)},
  1910  								CreatedBy:  "/bin/sh -c #(nop) COPY file:842584685f26edb24dc305d76894f51cfda2bad0c24a05e727f9d4905d184a70 in /php-app/composer.lock ",
  1911  								Comment:    "",
  1912  								EmptyLayer: false,
  1913  							},
  1914  							{
  1915  								Created:    v1.Time{Time: time.Date(2020, 2, 16, 10, 38, 41, 114114788, time.UTC)},
  1916  								CreatedBy:  "/bin/sh -c #(nop) COPY file:c6d0373d380252b91829a5bb3c81d5b1afa574c91cef7752d18170a231c31f6d in /ruby-app/Gemfile.lock ",
  1917  								Comment:    "",
  1918  								EmptyLayer: false,
  1919  							},
  1920  						},
  1921  						OS: "linux",
  1922  						RootFS: v1.RootFS{
  1923  							Type: "layers",
  1924  							DiffIDs: []v1.Hash{
  1925  								{
  1926  									Algorithm: "sha256",
  1927  									Hex:       "932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
  1928  								},
  1929  								{
  1930  									Algorithm: "sha256",
  1931  									Hex:       "dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5",
  1932  								},
  1933  								{
  1934  									Algorithm: "sha256",
  1935  									Hex:       "24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
  1936  								},
  1937  								{
  1938  									Algorithm: "sha256",
  1939  									Hex:       "a4595c43a874856bf95f3bfc4fbf78bbaa04c92c726276d4f64193a47ced0566",
  1940  								},
  1941  							},
  1942  						},
  1943  						Config: v1.Config{
  1944  							Env: []string{
  1945  								"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
  1946  								"SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt",
  1947  							},
  1948  							Hostname: "",
  1949  							Image:    "sha256:916390dcf84a1c7852e298f24fb5389a6e7801102086924e55eb08cd58d6a741",
  1950  						},
  1951  					},
  1952  				},
  1953  			},
  1954  		},
  1955  		{
  1956  			name:      "sad path, MissingBlobs returns an error",
  1957  			imagePath: "../../test/testdata/alpine-311.tar.gz",
  1958  			missingBlobsExpectation: cache.ArtifactCacheMissingBlobsExpectation{
  1959  				Args: cache.ArtifactCacheMissingBlobsArgs{
  1960  					ArtifactID: "sha256:c232b7d8ac8aa08aa767313d0b53084c4380d1c01a213a5971bdb039e6538313",
  1961  					BlobIDs:    []string{"sha256:0366f81c3cbeac047536f9ca133b5632544c8342544922c3ed8a3e51c0250897"},
  1962  				},
  1963  				Returns: cache.ArtifactCacheMissingBlobsReturns{
  1964  					Err: xerrors.New("MissingBlobs failed"),
  1965  				},
  1966  			},
  1967  			wantErr: "MissingBlobs failed",
  1968  		},
  1969  		{
  1970  			name:      "sad path, PutBlob returns an error",
  1971  			imagePath: "../../test/testdata/alpine-311.tar.gz",
  1972  			missingBlobsExpectation: cache.ArtifactCacheMissingBlobsExpectation{
  1973  				Args: cache.ArtifactCacheMissingBlobsArgs{
  1974  					ArtifactID: "sha256:c232b7d8ac8aa08aa767313d0b53084c4380d1c01a213a5971bdb039e6538313",
  1975  					BlobIDs:    []string{"sha256:0366f81c3cbeac047536f9ca133b5632544c8342544922c3ed8a3e51c0250897"},
  1976  				},
  1977  				Returns: cache.ArtifactCacheMissingBlobsReturns{
  1978  					MissingBlobIDs: []string{"sha256:0366f81c3cbeac047536f9ca133b5632544c8342544922c3ed8a3e51c0250897"},
  1979  				},
  1980  			},
  1981  			putBlobExpectations: []cache.ArtifactCachePutBlobExpectation{
  1982  				{
  1983  					Args: cache.ArtifactCachePutBlobArgs{
  1984  						BlobID: "sha256:0366f81c3cbeac047536f9ca133b5632544c8342544922c3ed8a3e51c0250897",
  1985  						BlobInfo: types.BlobInfo{
  1986  							SchemaVersion: types.BlobJSONSchemaVersion,
  1987  							Digest:        "",
  1988  							DiffID:        "sha256:beee9f30bc1f711043e78d4a2be0668955d4b761d587d6f60c2c8dc081efb203",
  1989  							CreatedBy:     "ADD file:0c4555f363c2672e350001f1293e689875a3760afe7b3f9146886afe67121cba in / ",
  1990  							OS: types.OS{
  1991  								Family: "alpine",
  1992  								Name:   "3.11.5",
  1993  							},
  1994  							Repository: &types.Repository{
  1995  								Family:  "alpine",
  1996  								Release: "3.11",
  1997  							},
  1998  							PackageInfos: []types.PackageInfo{
  1999  								{
  2000  									FilePath: "lib/apk/db/installed",
  2001  									Packages: alpinePkgs,
  2002  								},
  2003  							},
  2004  							Licenses: []types.LicenseFile{
  2005  								{
  2006  									Type:     "header",
  2007  									FilePath: "etc/ssl/misc/CA.pl",
  2008  									Findings: []types.LicenseFinding{
  2009  										{
  2010  											Name:       "OpenSSL",
  2011  											Confidence: 1,
  2012  											Link:       "https://spdx.org/licenses/OpenSSL.html",
  2013  										},
  2014  									},
  2015  								},
  2016  								{
  2017  									Type:     "header",
  2018  									FilePath: "etc/ssl/misc/tsget.pl",
  2019  									Findings: []types.LicenseFinding{
  2020  										{
  2021  											Name:       "OpenSSL",
  2022  											Confidence: 1,
  2023  											Link:       "https://spdx.org/licenses/OpenSSL.html",
  2024  										},
  2025  									},
  2026  								},
  2027  							},
  2028  						},
  2029  					},
  2030  					Returns: cache.ArtifactCachePutBlobReturns{
  2031  						Err: errors.New("put layer failed"),
  2032  					},
  2033  				},
  2034  			},
  2035  			wantErr: "put layer failed",
  2036  		},
  2037  		{
  2038  			name:      "sad path, PutBlob returns an error with multiple layers",
  2039  			imagePath: "../../test/testdata/vuln-image.tar.gz",
  2040  			missingBlobsExpectation: cache.ArtifactCacheMissingBlobsExpectation{
  2041  				Args: cache.ArtifactCacheMissingBlobsArgs{
  2042  					ArtifactID: "sha256:33f9415ed2cd5a9cef5d5144333619745b9ec0f851f0684dd45fa79c6b26a650",
  2043  					BlobIDs: []string{
  2044  						"sha256:db2b5b2f26f320b80ee549495888f111151fdb44fecb2c432dfd928e96978e74",
  2045  						"sha256:718d6a3d0a24966f2d9f64e0c86695d1bb896fe81df634b85300d34142c80174",
  2046  						"sha256:9f6bc14198fa983fd47079bcd82df1391bee8e529a8a131a0305874eb0a51ca0",
  2047  						"sha256:44264715b7132cd14cd956bf385d5f875603461f5adeafde7fdecabe2e266291",
  2048  					},
  2049  				},
  2050  				Returns: cache.ArtifactCacheMissingBlobsReturns{
  2051  					MissingBlobIDs: []string{
  2052  						"sha256:db2b5b2f26f320b80ee549495888f111151fdb44fecb2c432dfd928e96978e74",
  2053  						"sha256:718d6a3d0a24966f2d9f64e0c86695d1bb896fe81df634b85300d34142c80174",
  2054  						"sha256:9f6bc14198fa983fd47079bcd82df1391bee8e529a8a131a0305874eb0a51ca0",
  2055  						"sha256:44264715b7132cd14cd956bf385d5f875603461f5adeafde7fdecabe2e266291",
  2056  					},
  2057  				},
  2058  			},
  2059  			putBlobExpectations: []cache.ArtifactCachePutBlobExpectation{
  2060  				{
  2061  
  2062  					Args: cache.ArtifactCachePutBlobArgs{
  2063  						BlobID:           "sha256:db2b5b2f26f320b80ee549495888f111151fdb44fecb2c432dfd928e96978e74",
  2064  						BlobInfoAnything: true,
  2065  					},
  2066  
  2067  					Returns: cache.ArtifactCachePutBlobReturns{
  2068  						Err: errors.New("put layer failed"),
  2069  					},
  2070  				},
  2071  				{
  2072  
  2073  					Args: cache.ArtifactCachePutBlobArgs{
  2074  						BlobID:           "sha256:718d6a3d0a24966f2d9f64e0c86695d1bb896fe81df634b85300d34142c80174",
  2075  						BlobInfoAnything: true,
  2076  					},
  2077  
  2078  					Returns: cache.ArtifactCachePutBlobReturns{
  2079  						Err: errors.New("put layer failed"),
  2080  					},
  2081  				},
  2082  				{
  2083  
  2084  					Args: cache.ArtifactCachePutBlobArgs{
  2085  						BlobID:           "sha256:9f6bc14198fa983fd47079bcd82df1391bee8e529a8a131a0305874eb0a51ca0",
  2086  						BlobInfoAnything: true,
  2087  					},
  2088  
  2089  					Returns: cache.ArtifactCachePutBlobReturns{
  2090  						Err: errors.New("put layer failed"),
  2091  					},
  2092  				},
  2093  				{
  2094  
  2095  					Args: cache.ArtifactCachePutBlobArgs{
  2096  						BlobID:           "sha256:44264715b7132cd14cd956bf385d5f875603461f5adeafde7fdecabe2e266291",
  2097  						BlobInfoAnything: true,
  2098  					},
  2099  
  2100  					Returns: cache.ArtifactCachePutBlobReturns{
  2101  						Err: errors.New("put layer failed"),
  2102  					},
  2103  				},
  2104  			},
  2105  			wantErr: "put layer failed",
  2106  		},
  2107  		{
  2108  			name:      "sad path, PutArtifact returns an error",
  2109  			imagePath: "../../test/testdata/alpine-311.tar.gz",
  2110  			missingBlobsExpectation: cache.ArtifactCacheMissingBlobsExpectation{
  2111  				Args: cache.ArtifactCacheMissingBlobsArgs{
  2112  					ArtifactID: "sha256:c232b7d8ac8aa08aa767313d0b53084c4380d1c01a213a5971bdb039e6538313",
  2113  					BlobIDs:    []string{"sha256:0366f81c3cbeac047536f9ca133b5632544c8342544922c3ed8a3e51c0250897"},
  2114  				},
  2115  				Returns: cache.ArtifactCacheMissingBlobsReturns{
  2116  					MissingArtifact: true,
  2117  					MissingBlobIDs:  []string{"sha256:0366f81c3cbeac047536f9ca133b5632544c8342544922c3ed8a3e51c0250897"},
  2118  				},
  2119  			},
  2120  			putBlobExpectations: []cache.ArtifactCachePutBlobExpectation{
  2121  				{
  2122  					Args: cache.ArtifactCachePutBlobArgs{
  2123  						BlobID: "sha256:0366f81c3cbeac047536f9ca133b5632544c8342544922c3ed8a3e51c0250897",
  2124  						BlobInfo: types.BlobInfo{
  2125  							SchemaVersion: types.BlobJSONSchemaVersion,
  2126  							Digest:        "",
  2127  							DiffID:        "sha256:beee9f30bc1f711043e78d4a2be0668955d4b761d587d6f60c2c8dc081efb203",
  2128  							CreatedBy:     "ADD file:0c4555f363c2672e350001f1293e689875a3760afe7b3f9146886afe67121cba in / ",
  2129  							OS: types.OS{
  2130  								Family: "alpine",
  2131  								Name:   "3.11.5",
  2132  							},
  2133  							Repository: &types.Repository{
  2134  								Family:  "alpine",
  2135  								Release: "3.11",
  2136  							},
  2137  							PackageInfos: []types.PackageInfo{
  2138  								{
  2139  									FilePath: "lib/apk/db/installed",
  2140  									Packages: alpinePkgs,
  2141  								},
  2142  							},
  2143  							Licenses: []types.LicenseFile{
  2144  								{
  2145  									Type:     "header",
  2146  									FilePath: "etc/ssl/misc/CA.pl",
  2147  									Findings: []types.LicenseFinding{
  2148  										{
  2149  											Name:       "OpenSSL",
  2150  											Confidence: 1,
  2151  											Link:       "https://spdx.org/licenses/OpenSSL.html",
  2152  										},
  2153  									},
  2154  								},
  2155  								{
  2156  									Type:     "header",
  2157  									FilePath: "etc/ssl/misc/tsget.pl",
  2158  									Findings: []types.LicenseFinding{
  2159  										{
  2160  											Name:       "OpenSSL",
  2161  											Confidence: 1,
  2162  											Link:       "https://spdx.org/licenses/OpenSSL.html",
  2163  										},
  2164  									},
  2165  								},
  2166  							},
  2167  						},
  2168  					},
  2169  					Returns: cache.ArtifactCachePutBlobReturns{},
  2170  				},
  2171  			},
  2172  			putArtifactExpectations: []cache.ArtifactCachePutArtifactExpectation{
  2173  				{
  2174  					Args: cache.ArtifactCachePutArtifactArgs{
  2175  						ArtifactID: "sha256:c232b7d8ac8aa08aa767313d0b53084c4380d1c01a213a5971bdb039e6538313",
  2176  						ArtifactInfo: types.ArtifactInfo{
  2177  							SchemaVersion: types.ArtifactJSONSchemaVersion,
  2178  							Architecture:  "amd64",
  2179  							Created:       time.Date(2020, 3, 23, 21, 19, 34, 196162891, time.UTC),
  2180  							DockerVersion: "18.09.7",
  2181  							OS:            "linux",
  2182  						},
  2183  					},
  2184  					Returns: cache.ArtifactCachePutArtifactReturns{
  2185  						Err: errors.New("put artifact failed"),
  2186  					},
  2187  				},
  2188  			},
  2189  			wantErr: "put artifact failed",
  2190  		},
  2191  	}
  2192  	for _, tt := range tests {
  2193  		t.Run(tt.name, func(t *testing.T) {
  2194  			mockCache := new(cache.MockArtifactCache)
  2195  			mockCache.ApplyMissingBlobsExpectation(tt.missingBlobsExpectation)
  2196  			mockCache.ApplyPutBlobExpectations(tt.putBlobExpectations)
  2197  			mockCache.ApplyPutArtifactExpectations(tt.putArtifactExpectations)
  2198  
  2199  			img, err := image.NewArchiveImage(tt.imagePath)
  2200  			require.NoError(t, err)
  2201  
  2202  			a, err := image2.NewArtifact(img, mockCache, tt.artifactOpt)
  2203  			require.NoError(t, err)
  2204  
  2205  			got, err := a.Inspect(context.Background())
  2206  			if tt.wantErr != "" {
  2207  				assert.ErrorContains(t, err, tt.wantErr, tt.name)
  2208  				return
  2209  			}
  2210  			require.NoError(t, err, tt.name)
  2211  			assert.Equal(t, tt.want, got)
  2212  		})
  2213  	}
  2214  }