diff --git a/go.mod b/go.mod index 0b0cdde2..f08756e3 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/glebarez/sqlite v1.10.0 github.com/go-test/deep v1.1.0 github.com/google/go-cmp v0.6.0 + github.com/google/osv-scanner v1.5.0 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/gookit/color v1.5.4 github.com/hashicorp/go-cleanhttp v0.5.2 @@ -57,12 +58,12 @@ require ( github.com/Masterminds/sprig/v3 v3.2.3 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/Microsoft/hcsshim v0.11.4 // indirect - github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect + github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c // indirect github.com/acobaugh/osrelease v0.1.0 // indirect github.com/anchore/clio v0.0.0-20240209204744-cb94e40a4f65 // indirect github.com/anchore/fangs v0.0.0-20231201140849-5075d28d6d8b // indirect github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb // indirect - github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect + github.com/anchore/go-struct-converter v0.0.0-20230627203149-c72ef8859ca9 // indirect github.com/anchore/go-version v1.2.2-0.20210903204242-51efa5b487c4 // indirect github.com/anchore/packageurl-go v0.1.1-0.20240202171727-877e1747d426 // indirect github.com/anchore/stereoscope v0.0.2-0.20240216182029-6171ee21e1d5 // indirect @@ -163,6 +164,7 @@ require ( github.com/opencontainers/runc v1.1.12 // indirect github.com/opencontainers/runtime-spec v1.1.0-rc.1 // indirect github.com/opencontainers/selinux v1.11.0 // indirect + github.com/package-url/packageurl-go v0.1.2 // indirect github.com/pborman/indent v1.2.1 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect @@ -204,7 +206,7 @@ require ( go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect golang.org/x/crypto v0.19.0 // indirect - golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 // indirect + golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect golang.org/x/mod v0.15.0 // indirect golang.org/x/net v0.21.0 // indirect golang.org/x/oauth2 v0.15.0 // indirect diff --git a/go.sum b/go.sum index 0dedcec0..66717e11 100644 --- a/go.sum +++ b/go.sum @@ -221,8 +221,8 @@ github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYx github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8= github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= -github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg= -github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= +github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c h1:kMFnB0vCcX7IL/m9Y5LO+KQYv+t1CQOiFe6+SV2J7bE= +github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= github.com/acobaugh/osrelease v0.1.0 h1:Yb59HQDGGNhCj4suHaFQQfBps5wyoKLSSX/J/+UifRE= @@ -243,8 +243,9 @@ github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a h1:nJ2G8zWKASyVC github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a/go.mod h1:ubLFmlsv8/DFUQrZwY5syT5/8Er3ugSr4rDFwHsE3hg= github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb h1:iDMnx6LIjtjZ46C0akqveX83WFzhpTD3eqOthawb5vU= github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb/go.mod h1:DmTY2Mfcv38hsHbG78xMiTDdxFtkHpgYNVDPsF2TgHk= -github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 h1:aM1rlcoLz8y5B2r4tTLMiVTrMtpfY0O8EScKJxaSaEc= github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA= +github.com/anchore/go-struct-converter v0.0.0-20230627203149-c72ef8859ca9 h1:6COpXWpHbhWM1wgcQN95TdsmrLTba8KQfPgImBXzkjA= +github.com/anchore/go-struct-converter v0.0.0-20230627203149-c72ef8859ca9/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA= github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 h1:VzprUTpc0vW0nnNKJfJieyH/TZ9UYAnTZs5/gHTdAe8= github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04/go.mod h1:6dK64g27Qi1qGQZ67gFmBFvEHScy0/C8qhQhNe5B5pQ= github.com/anchore/go-version v1.2.2-0.20210903204242-51efa5b487c4 h1:rmZG77uXgE+o2gozGEBoUMpX27lsku+xrMwlmBZJtbg= @@ -529,6 +530,8 @@ github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIG github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/osv-scanner v1.5.0 h1:ln0i1o4fEu3iPlAIeSJg3zRxBEJjO+IvKDBMX/R6He0= +github.com/google/osv-scanner v1.5.0/go.mod h1:+BqMim8RGiZzPiXubV/UTvxQCJPxt1yCgZegn74oh8A= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -792,6 +795,8 @@ github.com/opencontainers/runtime-spec v1.1.0-rc.1 h1:wHa9jroFfKGQqFHj0I1fMRKLl0 github.com/opencontainers/runtime-spec v1.1.0-rc.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= +github.com/package-url/packageurl-go v0.1.2 h1:0H2DQt6DHd/NeRlVwW4EZ4oEI6Bn40XlNPRqegcxuo4= +github.com/package-url/packageurl-go v0.1.2/go.mod h1:uQd4a7Rh3ZsVg5j0lNyAfyxIeGde9yrlhjF78GzeW0c= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/indent v1.2.1 h1:lFiviAbISHv3Rf0jcuh489bi06hj98JsVMtIDZQb9yM= @@ -1037,8 +1042,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 h1:mchzmB1XO2pMaKFRqk/+MV3mgGG96aqaPXaMifQU47w= -golang.org/x/exp v0.0.0-20231108232855-2478ac86f678/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= diff --git a/pkg/data/transformers.go b/pkg/data/transformers.go index 531651f0..085e4f8b 100644 --- a/pkg/data/transformers.go +++ b/pkg/data/transformers.go @@ -1,6 +1,10 @@ package data -import "github.com/anchore/grype-db/pkg/provider/unmarshal" +import ( + osvModels "github.com/google/osv-scanner/pkg/models" + + "github.com/anchore/grype-db/pkg/provider/unmarshal" +) // Transformers are functions that know how ta take individual data shapes defined in the unmarshal package and // reshape the data into data.Entry objects that are writable by a data.Writer. Transformers are dependency-injected @@ -11,3 +15,4 @@ type MSRCTransformer func(entry unmarshal.MSRCVulnerability) ([]Entry, error) type NVDTransformer func(entry unmarshal.NVDVulnerability) ([]Entry, error) type OSTransformer func(entry unmarshal.OSVulnerability) ([]Entry, error) type MatchExclusionTransformer func(entry unmarshal.MatchExclusion) ([]Entry, error) +type OSVTransformer func(entry osvModels.Vulnerability) ([]Entry, error) diff --git a/pkg/process/processors/osv_processor.go b/pkg/process/processors/osv_processor.go new file mode 100644 index 00000000..5b3cead0 --- /dev/null +++ b/pkg/process/processors/osv_processor.go @@ -0,0 +1,54 @@ +package processors + +import ( + "io" + "strings" + + "github.com/anchore/grype-db/internal/log" + "github.com/anchore/grype-db/pkg/data" + "github.com/anchore/grype-db/pkg/provider/unmarshal" +) + +type osvProcessor struct { + transformer data.OSVTransformer +} + +func NewOSVProcessor(transformer data.OSVTransformer) data.Processor { + return &osvProcessor{ + transformer: transformer, + } +} + +func (p osvProcessor) Process(reader io.Reader) ([]data.Entry, error) { + var results []data.Entry + + entries, err := unmarshal.OSVVulnerabilityEntries(reader) + if err != nil { + return nil, err + } + + for _, entry := range entries { + transformedEntries, err := p.transformer(entry) + if err != nil { + return nil, err + } + + results = append(results, transformedEntries...) + } + + return results, nil +} + +func (p osvProcessor) IsSupported(schemaURL string) bool { + matchesSchemaType := strings.Contains(schemaURL, "https://raw.githubusercontent.com/anchore/vunnel/main/schema/vulnerability/osv/schema-") + if !matchesSchemaType { + return false + } + + if !strings.HasSuffix(schemaURL, "schema-1.6.1.json") { + log.WithFields("schema", schemaURL).Trace("unsupported OSV schema version") + return false + } + + return true +} diff --git a/pkg/process/processors/osv_processor_test.go b/pkg/process/processors/osv_processor_test.go new file mode 100644 index 00000000..eba0bb45 --- /dev/null +++ b/pkg/process/processors/osv_processor_test.go @@ -0,0 +1,34 @@ +package processors + +import ( + "os" + "testing" + + osvModels "github.com/google/osv-scanner/pkg/models" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/anchore/grype-db/pkg/data" + testUtils "github.com/anchore/grype-db/pkg/process/tests" +) + +func mockOSVProcessorTransform(vulnerability osvModels.Vulnerability) ([]data.Entry, error) { + return []data.Entry{ + { + DBSchemaVersion: 0, + Data: vulnerability, + }, + }, nil +} + +func TestOSVProcessor_Process(t *testing.T) { + f, err := os.Open("test-fixtures/osv.json") + require.NoError(t, err) + defer testUtils.CloseFile(f) + + processor := NewOSVProcessor(mockOSVProcessorTransform) + entries, err := processor.Process(f) + + require.NoError(t, err) + assert.Len(t, entries, 2) +} diff --git a/pkg/process/processors/test-fixtures/osv.json b/pkg/process/processors/test-fixtures/osv.json new file mode 100644 index 00000000..9ddd5bf5 --- /dev/null +++ b/pkg/process/processors/test-fixtures/osv.json @@ -0,0 +1,130 @@ +[ + { + "schema_version": "1.3.1", + "id": "GO-2023-2412", + "modified": "0001-01-01T00:00:00Z", + "published": "0001-01-01T00:00:00Z", + "aliases": [ + "GHSA-7ww5-4wqc-m92c" + ], + "summary": "RAPL accessibility in github.com/containerd/containerd", + "details": "RAPL accessibility in github.com/containerd/containerd", + "affected": [ + { + "package": { + "name": "github.com/containerd/containerd", + "ecosystem": "Go" + }, + "ranges": [ + { + "type": "SEMVER", + "events": [ + { + "introduced": "0" + }, + { + "fixed": "1.6.26" + }, + { + "introduced": "1.7.0" + }, + { + "fixed": "1.7.11" + } + ] + } + ], + "ecosystem_specific": { + "imports": [ + { + "path": "github.com/containerd/containerd/contrib/apparmor", + "symbols": [ + "DumpDefaultProfile", + "LoadDefaultProfile", + "generate" + ] + } + ] + } + } + ], + "references": [ + { + "type": "ADVISORY", + "url": "https://github.com/containerd/containerd/security/advisories/GHSA-7ww5-4wqc-m92c" + }, + { + "type": "FIX", + "url": "https://github.com/containerd/containerd/commit/67d356cb3095f3e8f8ad7d36f9a733fea1e7e28c" + }, + { + "type": "FIX", + "url": "https://github.com/containerd/containerd/commit/746b910f05855c8bfdb4415a1c0f958b234910e5" + } + ], + "database_specific": { + "url": "https://pkg.go.dev/vuln/GO-2023-2412" + } + }, + { + "schema_version": "1.3.1", + "id": "GO-2023-2413", + "modified": "0001-01-01T00:00:00Z", + "published": "0001-01-01T00:00:00Z", + "aliases": [ + "CVE-2023-49922", + "GHSA-hj4r-2c9c-29h3" + ], + "summary": "Sensitive information logged in github.com/elastic/beats/v7", + "details": "Sensitive information logged in github.com/elastic/beats/v7", + "affected": [ + { + "package": { + "name": "github.com/elastic/beats/v7", + "ecosystem": "Go" + }, + "ranges": [ + { + "type": "SEMVER", + "events": [ + { + "introduced": "0" + }, + { + "fixed": "7.17.16" + } + ] + } + ], + "ecosystem_specific": { + "imports": [ + { + "path": "github.com/elastic/beats/v7/libbeat/processors/script/javascript", + "symbols": [ + "jsProcessor.Run", + "session.runProcessFunc" + ] + } + ] + } + } + ], + "references": [ + { + "type": "ADVISORY", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-49922" + }, + { + "type": "FIX", + "url": "https://github.com/elastic/beats/commit/9bd7de84ab9c31bb4e1c0a348a7b7c26817a0996" + }, + { + "type": "WEB", + "url": "https://discuss.elastic.co/t/beats-and-elastic-agent-8-11-3-7-17-16-security-update-esa-2023-30/349180" + } + ], + "database_specific": { + "url": "https://pkg.go.dev/vuln/GO-2023-2413" + } + } +] diff --git a/pkg/provider/unmarshal/osv_vulnerability.go b/pkg/provider/unmarshal/osv_vulnerability.go new file mode 100644 index 00000000..0ac54b02 --- /dev/null +++ b/pkg/provider/unmarshal/osv_vulnerability.go @@ -0,0 +1,11 @@ +package unmarshal + +import ( + "io" + + osvModels "github.com/google/osv-scanner/pkg/models" +) + +func OSVVulnerabilityEntries(reader io.Reader) (osvModels.Vulnerabilities, error) { + return unmarshalSingleOrMulti[osvModels.Vulnerability](reader) +}