diff --git a/go.mod b/go.mod index 845e46d448..350472d7b4 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/aquasecurity/testdocker v0.0.0-20240730042311-4642e94c7fc8 github.com/aquasecurity/tml v0.6.1 github.com/aquasecurity/trivy-checks v1.6.1 - github.com/aquasecurity/trivy-db v0.0.0-20241209111357-8c398f13db0e + github.com/aquasecurity/trivy-db v0.0.0-20250227071930-8bd8a9b89e2d github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48 github.com/aquasecurity/trivy-kubernetes v0.7.0 github.com/aws/aws-sdk-go-v2 v1.34.0 @@ -80,7 +80,7 @@ require ( github.com/masahiro331/go-disk v0.0.0-20240625071113-56c933208fee github.com/masahiro331/go-ebs-file v0.0.0-20240917043618-e6d2bea5c32e github.com/masahiro331/go-ext4-filesystem v0.0.0-20240620024024-ca14e6327bbd - github.com/masahiro331/go-mvn-version v0.0.0-20210429150710-d3157d602a08 + github.com/masahiro331/go-mvn-version v0.0.0-20250131095131-f4974fa13b8a github.com/masahiro331/go-vmdk-parser v0.0.0-20221225061455-612096e4bbbd github.com/masahiro331/go-xfs-filesystem v0.0.0-20231205045356-1b22259a6c44 github.com/mattn/go-shellwords v1.0.12 @@ -437,4 +437,8 @@ require ( github.com/aws/aws-sdk-go-v2/service/sso v1.24.12 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.11 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.33.10 // indirect + github.com/oklog/ulid/v2 v2.1.0 // indirect + github.com/samber/oops v1.15.0 // indirect ) + +replace github.com/aquasecurity/trivy-db => github.com/DmitriyLewen/trivy-db v0.0.0-20250225102547-67e9b4dfc612 diff --git a/go.sum b/go.sum index 139008db5e..3410274733 100644 --- a/go.sum +++ b/go.sum @@ -685,6 +685,8 @@ github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7Oputl github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/DmitriyLewen/trivy-db v0.0.0-20250225102547-67e9b4dfc612 h1:T/H7M/RT9eSesHJdVVDQybAkTYNKI5RjyIeWpa2jK8o= +github.com/DmitriyLewen/trivy-db v0.0.0-20250225102547-67e9b4dfc612/go.mod h1:4bTsQPtMBN8v+UfUlE1aQBN1imftefnDafHBF85+aT8= github.com/GoogleCloudPlatform/docker-credential-gcr v2.0.5+incompatible h1:juIaKLLVhqzP55d8x4cSVgwyQv76Z55/fRv/UBr2KkQ= github.com/GoogleCloudPlatform/docker-credential-gcr v2.0.5+incompatible/go.mod h1:BB1eHdMLYEFuFdBlRMb0N7YGVdM5s6Pt0njxgvfbGGs= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw= @@ -805,8 +807,6 @@ github.com/aquasecurity/tml v0.6.1 h1:y2ZlGSfrhnn7t4ZJ/0rotuH+v5Jgv6BDDO5jB6A9gw github.com/aquasecurity/tml v0.6.1/go.mod h1:OnYMWY5lvI9ejU7yH9LCberWaaTBW7hBFsITiIMY2yY= github.com/aquasecurity/trivy-checks v1.6.1 h1:ANxKl+c9/k3Uk0YNQwpFBx++CG9Goi5T0YeN7Qimmf4= github.com/aquasecurity/trivy-checks v1.6.1/go.mod h1:xjHg4ivIIIFD7FFNpGrqxi1pRgAW1EXeG4VlkGiymjI= -github.com/aquasecurity/trivy-db v0.0.0-20241209111357-8c398f13db0e h1:O5j5SeCNBrXApgBTOobO06q4LMxJxIhcSGE7H6Y154E= -github.com/aquasecurity/trivy-db v0.0.0-20241209111357-8c398f13db0e/go.mod h1:gS8VhlNxhraiq60BBnJw9kGtjeMspQ9E8pX24jCL4jg= github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48 h1:JVgBIuIYbwG+ekC5lUHUpGJboPYiCcxiz06RCtz8neI= github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48/go.mod h1:Ldya37FLi0e/5Cjq2T5Bty7cFkzUDwTcPeQua+2M8i8= github.com/aquasecurity/trivy-kubernetes v0.7.0 h1:0pRJFSslUYd9xzQIEw1c0mS7k1Vv489nH/LsxeU6yME= @@ -1534,8 +1534,8 @@ github.com/masahiro331/go-ebs-file v0.0.0-20240917043618-e6d2bea5c32e h1:nCgF1JE github.com/masahiro331/go-ebs-file v0.0.0-20240917043618-e6d2bea5c32e/go.mod h1:XFWPTlAcEL733RUjbr0QBybdt6oK2DH7LZk8id2qtd4= github.com/masahiro331/go-ext4-filesystem v0.0.0-20240620024024-ca14e6327bbd h1:JEIW94K3spsvBI5Xb9PGhKSIza9/jxO1lF30tPCAJlA= github.com/masahiro331/go-ext4-filesystem v0.0.0-20240620024024-ca14e6327bbd/go.mod h1:3XMMY1M486mWGTD13WPItg6FsgflQR72ZMAkd+gsyoQ= -github.com/masahiro331/go-mvn-version v0.0.0-20210429150710-d3157d602a08 h1:AevUBW4cc99rAF8q8vmddIP8qd/0J5s/UyltGbp66dg= -github.com/masahiro331/go-mvn-version v0.0.0-20210429150710-d3157d602a08/go.mod h1:JOkBRrE1HvgTyjk6diFtNGgr8XJMtIfiBzkL5krqzVk= +github.com/masahiro331/go-mvn-version v0.0.0-20250131095131-f4974fa13b8a h1:eLvAzVoRfHEOl64OxFhepPf3vj7SKvXY/tFc3BS0b7s= +github.com/masahiro331/go-mvn-version v0.0.0-20250131095131-f4974fa13b8a/go.mod h1:jZ3F25l7DbD7l7DcA8aj7eo1EZ84nbzcQHBB4lCSrI8= github.com/masahiro331/go-vmdk-parser v0.0.0-20221225061455-612096e4bbbd h1:Y30EzvuoVp97b0unb/GOFXzBUKRXZXUN2e0wYmvC+ic= github.com/masahiro331/go-vmdk-parser v0.0.0-20221225061455-612096e4bbbd/go.mod h1:5f7mCJGW9cJb8SDn3z8qodGxpMCOo8d/2nls/tiwRrw= github.com/masahiro331/go-xfs-filesystem v0.0.0-20231205045356-1b22259a6c44 h1:VmSjn0UCyfXUNdePDr7uM/uZTnGSp+mKD5+cYkEoLx4= @@ -1635,6 +1635,8 @@ github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU= +github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= github.com/oleiade/reflections v1.0.1 h1:D1XO3LVEYroYskEsoSiGItp9RUxG6jWnCVvrqH0HHQM= github.com/oleiade/reflections v1.0.1/go.mod h1:rdFxbxq4QXVZWj0F+e9jqjDkc7dbp97vkRixKo2JR60= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -1678,6 +1680,7 @@ github.com/owenrumney/squealer v1.2.10 h1:Yxxy30sOhaK8/FeneHklV0sA6DP4UjUpky2opj github.com/owenrumney/squealer v1.2.10/go.mod h1:V72uafpqPERMaJ/pA1MwK/dI0QRzLHCLnh6MqYmjFzY= github.com/package-url/packageurl-go v0.1.3 h1:4juMED3hHiz0set3Vq3KeQ75KD1avthoXLtmE3I0PLs= github.com/package-url/packageurl-go v0.1.3/go.mod h1:nKAWB8E6uk1MHqiS/lQb9pYBGH2+mdJ2PJc2s50dQY0= +github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw= github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= @@ -1769,6 +1772,8 @@ github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6g github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew= github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o= +github.com/samber/oops v1.15.0 h1:/mF33KAqA2TugU6y/tomFpK6G6mJB7g0aqRyHkaSIeg= +github.com/samber/oops v1.15.0/go.mod h1:9LpLZkpjojEt/of7EpG5o65i/Lp23ddDvGhg2L871Ow= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= github.com/sassoftware/go-rpmutils v0.4.0 h1:ojND82NYBxgwrV+mX1CWsd5QJvvEZTKddtCdFLPWhpg= diff --git a/pkg/db/db.go b/pkg/db/db.go index 99f7e1c8ad..2d617e0942 100644 --- a/pkg/db/db.go +++ b/pkg/db/db.go @@ -2,6 +2,7 @@ package db import ( "context" + "errors" "fmt" "os" "path/filepath" @@ -96,16 +97,24 @@ func NewClient(dbDir string, quiet bool, opts ...Option) *Client { // NeedsUpdate check is DB needs update func (c *Client) NeedsUpdate(ctx context.Context, cliVersion string, skip bool) (bool, error) { + var noRequiredFiles bool + if _, err := os.Stat(db.Path(c.dbDir)); errors.Is(err, os.ErrNotExist) { + log.DebugContext(ctx, "There is no db file") + noRequiredFiles = true + } meta, err := c.metadata.Get() if err != nil { log.DebugContext(ctx, "There is no valid metadata file", log.Err(err)) - if skip { - log.ErrorContext(ctx, "The first run cannot skip downloading DB") - return false, xerrors.New("--skip-update cannot be specified on the first run") - } + noRequiredFiles = true + meta = metadata.Metadata{Version: db.SchemaVersion} } + if skip && noRequiredFiles { + log.ErrorContext(ctx, "The first run cannot skip downloading DB") + return false, xerrors.New("--skip-update cannot be specified on the first run") + } + if db.SchemaVersion < meta.Version { log.ErrorContext(ctx, "Trivy version is old. Update to the latest version.", log.String("version", cliVersion)) return false, xerrors.Errorf("the version of DB schema doesn't match. Local DB: %d, Expected: %d", diff --git a/pkg/db/db_test.go b/pkg/db/db_test.go index 2fd83aa873..574aa636b8 100644 --- a/pkg/db/db_test.go +++ b/pkg/db/db_test.go @@ -21,14 +21,16 @@ func TestClient_NeedsUpdate(t *testing.T) { timeNextUpdateDay2 := time.Date(2019, 10, 2, 0, 0, 0, 0, time.UTC) tests := []struct { - name string - skip bool - metadata metadata.Metadata - want bool - wantErr string + name string + skip bool + dbFileExists bool + metadata metadata.Metadata + want bool + wantErr string }{ { - name: "happy path", + name: "happy path", + dbFileExists: true, metadata: metadata.Metadata{ Version: db.SchemaVersion, NextUpdate: timeNextUpdateDay1, @@ -36,12 +38,19 @@ func TestClient_NeedsUpdate(t *testing.T) { want: true, }, { - name: "happy path for first run", - metadata: metadata.Metadata{}, - want: true, + name: "happy path for first run", + dbFileExists: true, + metadata: metadata.Metadata{}, + want: true, }, { - name: "happy path with old schema version", + name: "happy path for first run without trivy.db", + dbFileExists: false, + want: true, + }, + { + name: "happy path with old schema version", + dbFileExists: true, metadata: metadata.Metadata{ Version: 0, NextUpdate: timeNextUpdateDay1, @@ -49,7 +58,8 @@ func TestClient_NeedsUpdate(t *testing.T) { want: true, }, { - name: "happy path with --skip-update", + name: "happy path with --skip-update", + dbFileExists: true, metadata: metadata.Metadata{ Version: db.SchemaVersion, NextUpdate: timeNextUpdateDay1, @@ -58,7 +68,8 @@ func TestClient_NeedsUpdate(t *testing.T) { want: false, }, { - name: "skip downloading DB", + name: "skip downloading DB", + dbFileExists: true, metadata: metadata.Metadata{ Version: db.SchemaVersion, NextUpdate: timeNextUpdateDay2, @@ -66,7 +77,8 @@ func TestClient_NeedsUpdate(t *testing.T) { want: false, }, { - name: "newer schema version", + name: "newer schema version", + dbFileExists: true, metadata: metadata.Metadata{ Version: db.SchemaVersion + 1, NextUpdate: timeNextUpdateDay2, @@ -75,13 +87,21 @@ func TestClient_NeedsUpdate(t *testing.T) { db.SchemaVersion+1, db.SchemaVersion), }, { - name: "--skip-update on the first run", - metadata: metadata.Metadata{}, - skip: true, - wantErr: "--skip-update cannot be specified on the first run", + name: "--skip-update without trivy.db on the first run", + dbFileExists: false, + skip: true, + wantErr: "--skip-update cannot be specified on the first run", }, { - name: "--skip-update with different schema version", + name: "--skip-update without metadata.json on the first run", + dbFileExists: true, + metadata: metadata.Metadata{}, + skip: true, + wantErr: "--skip-update cannot be specified on the first run", + }, + { + name: "--skip-update with different schema version", + dbFileExists: true, metadata: metadata.Metadata{ Version: 0, NextUpdate: timeNextUpdateDay1, @@ -91,7 +111,8 @@ func TestClient_NeedsUpdate(t *testing.T) { 0, db.SchemaVersion), }, { - name: "happy with old DownloadedAt", + name: "happy with old DownloadedAt", + dbFileExists: true, metadata: metadata.Metadata{ Version: db.SchemaVersion, NextUpdate: timeNextUpdateDay1, @@ -100,7 +121,8 @@ func TestClient_NeedsUpdate(t *testing.T) { want: true, }, { - name: "skip downloading DB with recent DownloadedAt", + name: "skip downloading DB with recent DownloadedAt", + dbFileExists: true, metadata: metadata.Metadata{ Version: db.SchemaVersion, NextUpdate: timeNextUpdateDay1, @@ -119,6 +141,11 @@ func TestClient_NeedsUpdate(t *testing.T) { require.NoError(t, err) } + if tt.dbFileExists { + err := db.Init(dbDir) + require.NoError(t, err) + } + // Set a fake time ctx := clock.With(context.Background(), time.Date(2019, 10, 1, 0, 0, 0, 0, time.UTC)) @@ -138,7 +165,6 @@ func TestClient_NeedsUpdate(t *testing.T) { } func TestClient_Download(t *testing.T) { - tests := []struct { name string input string diff --git a/pkg/detector/library/driver_test.go b/pkg/detector/library/driver_test.go index dc82b58067..fa4eb8a6ab 100644 --- a/pkg/detector/library/driver_test.go +++ b/pkg/detector/library/driver_test.go @@ -155,7 +155,7 @@ func TestDriver_Detect(t *testing.T) { pkgName: "symfony/symfony", pkgVer: "5.1.5", }, - wantErr: "failed to unmarshal advisory JSON", + wantErr: "json unmarshal error", }, { name: "duplicated version in advisory", diff --git a/pkg/detector/ospkg/debian/debian_test.go b/pkg/detector/ospkg/debian/debian_test.go index ef7edbb7a1..fed30e2940 100644 --- a/pkg/detector/ospkg/debian/debian_test.go +++ b/pkg/detector/ospkg/debian/debian_test.go @@ -107,7 +107,7 @@ func TestScanner_Detect(t *testing.T) { }, }, }, - wantErr: "failed to unmarshal advisory JSON", + wantErr: "failed to get debian advisories", }, } for _, tt := range tests { diff --git a/pkg/detector/ospkg/oracle/oracle_test.go b/pkg/detector/ospkg/oracle/oracle_test.go index d33c42f416..76986a2970 100644 --- a/pkg/detector/ospkg/oracle/oracle_test.go +++ b/pkg/detector/ospkg/oracle/oracle_test.go @@ -331,7 +331,7 @@ func TestScanner_Detect(t *testing.T) { }, }, }, - wantErr: "failed to unmarshal advisory JSON", + wantErr: "failed to get Oracle Linux advisory", }, } diff --git a/pkg/detector/ospkg/photon/photon_test.go b/pkg/detector/ospkg/photon/photon_test.go index c450960f4c..e737083020 100644 --- a/pkg/detector/ospkg/photon/photon_test.go +++ b/pkg/detector/ospkg/photon/photon_test.go @@ -86,7 +86,7 @@ func TestScanner_Detect(t *testing.T) { }, }, }, - wantErr: "failed to get Photon advisories", + wantErr: "failed to get Photon Linux advisory", }, } for _, tt := range tests { diff --git a/pkg/detector/ospkg/suse/suse_test.go b/pkg/detector/ospkg/suse/suse_test.go index 420eb2a0d0..f3ca736edd 100644 --- a/pkg/detector/ospkg/suse/suse_test.go +++ b/pkg/detector/ospkg/suse/suse_test.go @@ -209,7 +209,7 @@ func TestScanner_Detect(t *testing.T) { }, }, }, - wantErr: "failed to get SUSE advisories", + wantErr: "failed to get SUSE advisory", }, } for _, tt := range tests {