diff --git a/.github/workflows/semantic-pr.yaml b/.github/workflows/semantic-pr.yaml index 168d86dc92..200e7ce1ed 100644 --- a/.github/workflows/semantic-pr.yaml +++ b/.github/workflows/semantic-pr.yaml @@ -70,6 +70,7 @@ jobs: go c c++ + elixir os lang diff --git a/docs/community/contribute/pr.md b/docs/community/contribute/pr.md index fde246fedf..828d31d984 100644 --- a/docs/community/contribute/pr.md +++ b/docs/community/contribute/pr.md @@ -80,6 +80,7 @@ language: - dotnet - java - go +- elixir vuln: diff --git a/docs/docs/vulnerability/detection/data-source.md b/docs/docs/vulnerability/detection/data-source.md index 9d0f107eb9..bd019bc7c8 100644 --- a/docs/docs/vulnerability/detection/data-source.md +++ b/docs/docs/vulnerability/detection/data-source.md @@ -20,23 +20,24 @@ # Programming Language -| Language | Source | Commercial Use | Delay[^1]| -|----------|-----------------------------------------------------|:---------------:|:--------:| -| PHP | [PHP Security Advisories Database][php] | ✅ | - | -| | [GitHub Advisory Database (Composer)][php-ghsa] | ✅ | - | -| Python | [GitHub Advisory Database (pip)][python-ghsa] | ✅ | - | -| | [Open Source Vulnerabilities (PyPI)][python-osv] | ✅ | - | -| Ruby | [Ruby Advisory Database][ruby] | ✅ | - | -| | [GitHub Advisory Database (RubyGems)][ruby-ghsa] | ✅ | - | -| Node.js | [Ecosystem Security Working Group][nodejs] | ✅ | - | -| | [GitHub Advisory Database (npm)][nodejs-ghsa] | ✅ | - | -| Java | [GitLab Advisories Community][gitlab] | ✅ | 1 month | -| | [GitHub Advisory Database (Maven)][java-ghsa] | ✅ | - | -| Go | [GitLab Advisories Community][gitlab] | ✅ | 1 month | -| | [The Go Vulnerability Database][go] | ✅ | - | -| Rust | [Open Source Vulnerabilities (crates.io)][rust-osv] | ✅ | - | -| .NET | [GitHub Advisory Database (NuGet)][dotnet-ghsa] | ✅ | - | -| C/C++ | [GitLab Advisories Community][gitlab] | ✅ | 1 month | +| Language | Source | Commercial Use | Delay[^1] | +|----------|-----------------------------------------------------|:--------------:|:---------:| +| PHP | [PHP Security Advisories Database][php] | ✅ | - | +| | [GitHub Advisory Database (Composer)][php-ghsa] | ✅ | - | +| Python | [GitHub Advisory Database (pip)][python-ghsa] | ✅ | - | +| | [Open Source Vulnerabilities (PyPI)][python-osv] | ✅ | - | +| Ruby | [Ruby Advisory Database][ruby] | ✅ | - | +| | [GitHub Advisory Database (RubyGems)][ruby-ghsa] | ✅ | - | +| Node.js | [Ecosystem Security Working Group][nodejs] | ✅ | - | +| | [GitHub Advisory Database (npm)][nodejs-ghsa] | ✅ | - | +| Java | [GitLab Advisories Community][gitlab] | ✅ | 1 month | +| | [GitHub Advisory Database (Maven)][java-ghsa] | ✅ | - | +| Go | [GitLab Advisories Community][gitlab] | ✅ | 1 month | +| | [The Go Vulnerability Database][go] | ✅ | - | +| Rust | [Open Source Vulnerabilities (crates.io)][rust-osv] | ✅ | - | +| .NET | [GitHub Advisory Database (NuGet)][dotnet-ghsa] | ✅ | - | +| C/C++ | [GitLab Advisories Community][gitlab] | ✅ | 1 month | +| Elixir | [GitHub Advisory Database (Erlang)][erlang-ghsa] | ✅ | | [^1]: Intentional delay between vulnerability disclosure and registration in the DB @@ -78,6 +79,7 @@ The severity is from the selected data source. If the data source does not provi [nodejs-ghsa]: https://github.com/advisories?query=ecosystem%3Anpm [java-ghsa]: https://github.com/advisories?query=ecosystem%3Amaven [dotnet-ghsa]: https://github.com/advisories?query=ecosystem%3Anuget +[erlang-ghsa]: https://github.com/advisories?query=ecosystem%3Aerlang [php]: https://github.com/FriendsOfPHP/security-advisories [ruby]: https://github.com/rubysec/ruby-advisory-db diff --git a/docs/docs/vulnerability/detection/language.md b/docs/docs/vulnerability/detection/language.md index 02922fbc71..9a584a9c55 100644 --- a/docs/docs/vulnerability/detection/language.md +++ b/docs/docs/vulnerability/detection/language.md @@ -27,6 +27,7 @@ | Rust | Cargo.lock | ✅ | ✅ | ✅ | ✅ | included | - | | | Binaries built with [cargo-auditable](https://github.com/rust-secure-code/cargo-auditable) | ✅ | ✅ | - | - | excluded | - | | C/C++ | conan.lock[^13] | - | - | ✅ | ✅ | excluded | - | +| Elixir | mix.lock[^13] | - | - | ✅ | ✅ | excluded | ✅ | The path of these files does not matter. @@ -44,4 +45,4 @@ Example: [Dockerfile](https://github.com/aquasecurity/trivy-ci-test/blob/main/Do [^10]: ✅ means "enabled" and `-` means "disabled" in the filesystem scanning [^11]: ✅ means "enabled" and `-` means "disabled" in the git repository scanning [^12]: ✅ means that Trivy detects line numbers where each dependency is declared in the scanned file. Only supported in [json](../examples/report.md#json) and [sarif](../examples/report.md#sarif) formats. SARIF uses `startline == 1 and endline == 1` for unsupported file types -[^13]: To scan a filename other than the default filename(`conan.lock`) use [file-patterns](../examples/others.md#file-patterns) +[^13]: To scan a filename other than the default filename use [file-patterns](../examples/others.md#file-patterns) diff --git a/go.mod b/go.mod index 225b9c512b..cb0dd097b3 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/alicebob/miniredis/v2 v2.23.0 github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986 github.com/aquasecurity/defsec v0.82.7-0.20221225070347-3a6cfb67e460 - github.com/aquasecurity/go-dep-parser v0.0.0-20221208150335-299772f066c4 + github.com/aquasecurity/go-dep-parser v0.0.0-20221227140654-09a64a5d9b51 github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce github.com/aquasecurity/go-npm-version v0.0.0-20201110091526-0b796d180798 github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46 @@ -19,7 +19,7 @@ require ( github.com/aquasecurity/table v1.8.0 github.com/aquasecurity/testdocker v0.0.0-20210911155206-e1e85f5a1516 github.com/aquasecurity/tml v0.6.1 - github.com/aquasecurity/trivy-db v0.0.0-20221208102935-e829718a223f + github.com/aquasecurity/trivy-db v0.0.0-20221227141502-af78ecb7db4c github.com/aquasecurity/trivy-kubernetes v0.3.1-0.20221021174315-8d74450b4506 github.com/aws/aws-sdk-go v1.44.136 github.com/aws/aws-sdk-go-v2 v1.17.1 diff --git a/go.sum b/go.sum index 6be07f7983..2f2f30f029 100644 --- a/go.sum +++ b/go.sum @@ -195,8 +195,8 @@ github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986 h1:2a30 github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986/go.mod h1:NT+jyeCzXk6vXR5MTkdn4z64TgGfE5HMLC8qfj5unl8= github.com/aquasecurity/defsec v0.82.7-0.20221225070347-3a6cfb67e460 h1:XHYo9HDWlrn3l+GH1ZTVUQAeP//r/iyEVUoP4Rmhuuw= github.com/aquasecurity/defsec v0.82.7-0.20221225070347-3a6cfb67e460/go.mod h1:sUdW6pzASralDcs+CDOE+QpWfBJt3/PY1Qbg8CS5flg= -github.com/aquasecurity/go-dep-parser v0.0.0-20221208150335-299772f066c4 h1:cFQv/JghmN6dC/vuu6JbDkziwhBgLPfQvyi/TxJN+6I= -github.com/aquasecurity/go-dep-parser v0.0.0-20221208150335-299772f066c4/go.mod h1:ZCiGJgdQxCateSw3nPMwZvp9J/+nU8/3DcGY/NO71e4= +github.com/aquasecurity/go-dep-parser v0.0.0-20221227140654-09a64a5d9b51 h1:1mbTWnP/NzDrbyYaDzS2xIxuoAuhY3N62qZCTuSqfSo= +github.com/aquasecurity/go-dep-parser v0.0.0-20221227140654-09a64a5d9b51/go.mod h1:ZCiGJgdQxCateSw3nPMwZvp9J/+nU8/3DcGY/NO71e4= github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce h1:QgBRgJvtEOBtUXilDb1MLi1p1MWoyFDXAu5DEUl5nwM= github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce/go.mod h1:HXgVzOPvXhVGLJs4ZKO817idqr/xhwsTcj17CLYY74s= github.com/aquasecurity/go-mock-aws v0.0.0-20220726154943-99847deb62b0 h1:tihCUjLWkF0b1SAjAKcFltUs3SpsqGrLtI+Frye0D10= @@ -217,8 +217,8 @@ github.com/aquasecurity/testdocker v0.0.0-20210911155206-e1e85f5a1516 h1:moQmzbp github.com/aquasecurity/testdocker v0.0.0-20210911155206-e1e85f5a1516/go.mod h1:gTd97VdQ0rg8Mkiic3rPgNOQdprZ7feTAhiD5mGQjgM= github.com/aquasecurity/tml v0.6.1 h1:y2ZlGSfrhnn7t4ZJ/0rotuH+v5Jgv6BDDO5jB6A9gwo= github.com/aquasecurity/tml v0.6.1/go.mod h1:OnYMWY5lvI9ejU7yH9LCberWaaTBW7hBFsITiIMY2yY= -github.com/aquasecurity/trivy-db v0.0.0-20221208102935-e829718a223f h1:M0nc6W/uVEGXSG3iHEEGujJB2vtMNx21iIeP6OM5Cb4= -github.com/aquasecurity/trivy-db v0.0.0-20221208102935-e829718a223f/go.mod h1:/nULgnDeq/JMPMVwE1dmf4kWlYn++7VrM3O2naj4BHA= +github.com/aquasecurity/trivy-db v0.0.0-20221227141502-af78ecb7db4c h1:CgJiXxVxgFOQ4btP97LEYqEHnx++FRpf2IJEXJV+xHs= +github.com/aquasecurity/trivy-db v0.0.0-20221227141502-af78ecb7db4c/go.mod h1:/nULgnDeq/JMPMVwE1dmf4kWlYn++7VrM3O2naj4BHA= github.com/aquasecurity/trivy-kubernetes v0.3.1-0.20221021174315-8d74450b4506 h1:maijOWmI5Ec/R7V0wpXoqvQC7fTjQD+PbDktKIK1VXs= github.com/aquasecurity/trivy-kubernetes v0.3.1-0.20221021174315-8d74450b4506/go.mod h1:xXd1m0iRJrz3ISbOXVDaR4hCWoSrF4RbIfNTN4dTrjY= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= diff --git a/integration/fs_test.go b/integration/fs_test.go index 7933f7c650..1a43baa0b8 100644 --- a/integration/fs_test.go +++ b/integration/fs_test.go @@ -147,6 +147,15 @@ func TestFilesystem(t *testing.T) { }, golden: "testdata/cocoapods.json.golden", }, + { + name: "mix.lock", + args: args{ + securityChecks: "vuln", + listAllPkgs: true, + input: "testdata/fixtures/fs/mixlock", + }, + golden: "testdata/mix.lock.json.golden", + }, { name: "dockerfile", args: args{ diff --git a/integration/testdata/fixtures/db/data-source.yaml b/integration/testdata/fixtures/db/data-source.yaml index fad2fee77b..2611842c21 100644 --- a/integration/testdata/fixtures/db/data-source.yaml +++ b/integration/testdata/fixtures/db/data-source.yaml @@ -30,6 +30,11 @@ ID: "ghsa" Name: "GitHub Security Advisory RubyGems" URL: "https://github.com/advisories?query=type%3Areviewed+ecosystem%3Arubygems" + - key: "erlang::GitHub Security Advisory Erlang" + value: + ID: "ghsa" + Name: "GitHub Security Advisory Erlang" + URL: "https://github.com/advisories?query=type%3Areviewed+ecosystem%3Aerlang" - key: Oracle Linux 8 value: ID: "oracle-oval" diff --git a/integration/testdata/fixtures/db/erlang.yaml b/integration/testdata/fixtures/db/erlang.yaml new file mode 100644 index 0000000000..a5fd04d193 --- /dev/null +++ b/integration/testdata/fixtures/db/erlang.yaml @@ -0,0 +1,10 @@ +- bucket: erlang::GitHub Security Advisory Erlang + pairs: + - bucket: phoenix + pairs: + - key: CVE-2022-42975 + value: + PatchedVersions: + - 1.6.14 + VulnerableVersions: + - "<= 1.6.14" \ No newline at end of file diff --git a/integration/testdata/fixtures/db/vulnerability.yaml b/integration/testdata/fixtures/db/vulnerability.yaml index d136a075ec..b530008378 100644 --- a/integration/testdata/fixtures/db/vulnerability.yaml +++ b/integration/testdata/fixtures/db/vulnerability.yaml @@ -1253,6 +1253,24 @@ - https://alephsecurity.com/vulns/aleph-2018004 PublishedDate: "2022-06-22T15:08:47Z" LastModifiedDate: "2022-06-27T18:37:23Z" + - key: CVE-2022-42975 + value: + Title: "Phoenix before 1.6.14 mishandles check_origin wildcarding" + Description: "socket/transport.ex in Phoenix before 1.6.14 mishandles check_origin wildcarding. NOTE: LiveView applications are unaffected by default because of the presence of a LiveView CSRF token." + Severity: HIGH + VendorSeverity: + ghsa: 3 + CVSS: + ghsa: + V3Vector: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N" + V3Score: 7.5 + References: + - https://nvd.nist.gov/vuln/detail/CVE-2022-42975 + - https://github.com/phoenixframework/phoenix/commit/6e7185b33a59e0b1d1c0b4223adf340a73e963ae + - https://hexdocs.pm/phoenix/1.6.14/changelog.html#1-6-14-2022-10-10 + - https://github.com/advisories/GHSA-p8f7-22gq-m7j9 + PublishedDate: "2022-10-17T12:00:27Z" + LastModifiedDate: "2022-10-18T18:01:44Z" - key: CVE-2022-22965 value: Title: "spring-framework: RCE via Data Binding on JDK 9+" diff --git a/integration/testdata/fixtures/fs/mixlock/mix.lock b/integration/testdata/fixtures/fs/mixlock/mix.lock new file mode 100644 index 0000000000..a13ebcf57c --- /dev/null +++ b/integration/testdata/fixtures/fs/mixlock/mix.lock @@ -0,0 +1,12 @@ +%{ + "castore": {:hex, :castore, "0.1.18", "deb5b9ab02400561b6f5708f3e7660fc35ca2d51bfc6a940d2f513f89c2975fc", [:mix], [], "hexpm", "61bbaf6452b782ef80b33cdb45701afbcf0a918a45ebe7e73f1130d661e66a06"}, + "jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"}, + "phoenix": {:hex, :phoenix, "1.6.13", "0a1d96bbc10747fd83525370d691953cdb6f3ccbac61aa01b4acb012474b047d", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 1.0 or ~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d70ab9fbf6b394755ea88b644d34d79d8b146e490973151f248cacd122d20672"}, + "phoenix_html": {:hex, :phoenix_html, "3.2.0", "1c1219d4b6cb22ac72f12f73dc5fad6c7563104d083f711c3fcd8551a1f4ae11", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "36ec97ba56d25c0136ef1992c37957e4246b649d620958a1f9fa86165f8bc54f"}, + "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.1", "ba04e489ef03763bf28a17eb2eaddc2c20c6d217e2150a61e3298b0f4c2012b5", [:mix], [], "hexpm", "81367c6d1eea5878ad726be80808eb5a787a23dee699f96e72b1109c57cdd8d9"}, + "phoenix_template": {:hex, :phoenix_template, "1.0.0", "c57bc5044f25f007dc86ab21895688c098a9f846a8dda6bc40e2d0ddc146e38f", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "1b066f99a26fd22064c12b2600a9a6e56700f591bf7b20b418054ea38b4d4357"}, + "phoenix_view": {:hex, :phoenix_view, "2.0.1", "a653e3d9d944aace0a064e4a13ad473ffa68f7bc4ca42dbf83cc1d464f1fb295", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}], "hexpm", "6c358e2cefc5f341c728914b867c556bbfd239fed9e881bac257d70cb2b8a6f6"}, + "plug": {:hex, :plug, "1.14.0", "ba4f558468f69cbd9f6b356d25443d0b796fbdc887e03fa89001384a9cac638f", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "bf020432c7d4feb7b3af16a0c2701455cbbbb95e5b6866132cb09eb0c29adc14"}, + "plug_crypto": {:hex, :plug_crypto, "1.2.3", "8f77d13aeb32bfd9e654cb68f0af517b371fb34c56c9f2b58fe3df1235c1251a", [:mix], [], "hexpm", "b5672099c6ad5c202c45f5a403f21a3411247f164e4a8fab056e5cd8a290f4a2"}, + "telemetry": {:hex, :telemetry, "1.1.0", "a589817034a27eab11144ad24d5c0f9fab1f58173274b1e9bae7074af9cbee51", [:rebar3], [], "hexpm", "b727b2a1f75614774cff2d7565b64d0dfa5bd52ba517f16543e6fc7efcc0df48"}, +} \ No newline at end of file diff --git a/integration/testdata/mix.lock.json.golden b/integration/testdata/mix.lock.json.golden new file mode 100644 index 0000000000..53cf0e1ab8 --- /dev/null +++ b/integration/testdata/mix.lock.json.golden @@ -0,0 +1,180 @@ +{ + "SchemaVersion": 2, + "ArtifactName": "testdata/fixtures/fs/mixlock", + "ArtifactType": "filesystem", + "Metadata": { + "ImageConfig": { + "architecture": "", + "created": "0001-01-01T00:00:00Z", + "os": "", + "rootfs": { + "type": "", + "diff_ids": null + }, + "config": {} + } + }, + "Results": [ + { + "Target": "mix.lock", + "Class": "lang-pkgs", + "Type": "hex", + "Packages": [ + { + "ID": "castore@0.1.18", + "Name": "castore", + "Version": "0.1.18", + "Layer": {}, + "Locations": [ + { + "StartLine": 2, + "EndLine": 2 + } + ] + }, + { + "ID": "jason@1.4.0", + "Name": "jason", + "Version": "1.4.0", + "Layer": {}, + "Locations": [ + { + "StartLine": 3, + "EndLine": 3 + } + ] + }, + { + "ID": "phoenix@1.6.13", + "Name": "phoenix", + "Version": "1.6.13", + "Layer": {}, + "Locations": [ + { + "StartLine": 4, + "EndLine": 4 + } + ] + }, + { + "ID": "phoenix_html@3.2.0", + "Name": "phoenix_html", + "Version": "3.2.0", + "Layer": {}, + "Locations": [ + { + "StartLine": 5, + "EndLine": 5 + } + ] + }, + { + "ID": "phoenix_pubsub@2.1.1", + "Name": "phoenix_pubsub", + "Version": "2.1.1", + "Layer": {}, + "Locations": [ + { + "StartLine": 6, + "EndLine": 6 + } + ] + }, + { + "ID": "phoenix_template@1.0.0", + "Name": "phoenix_template", + "Version": "1.0.0", + "Layer": {}, + "Locations": [ + { + "StartLine": 7, + "EndLine": 7 + } + ] + }, + { + "ID": "phoenix_view@2.0.1", + "Name": "phoenix_view", + "Version": "2.0.1", + "Layer": {}, + "Locations": [ + { + "StartLine": 8, + "EndLine": 8 + } + ] + }, + { + "ID": "plug@1.14.0", + "Name": "plug", + "Version": "1.14.0", + "Layer": {}, + "Locations": [ + { + "StartLine": 9, + "EndLine": 9 + } + ] + }, + { + "ID": "plug_crypto@1.2.3", + "Name": "plug_crypto", + "Version": "1.2.3", + "Layer": {}, + "Locations": [ + { + "StartLine": 10, + "EndLine": 10 + } + ] + }, + { + "ID": "telemetry@1.1.0", + "Name": "telemetry", + "Version": "1.1.0", + "Layer": {}, + "Locations": [ + { + "StartLine": 11, + "EndLine": 11 + } + ] + } + ], + "Vulnerabilities": [ + { + "VulnerabilityID": "CVE-2022-42975", + "PkgName": "phoenix", + "PkgID": "phoenix@1.6.13", + "InstalledVersion": "1.6.13", + "FixedVersion": "1.6.14", + "Layer": {}, + "SeveritySource": "ghsa", + "PrimaryURL": "https://avd.aquasec.com/nvd/cve-2022-42975", + "DataSource": { + "ID": "ghsa", + "Name": "GitHub Security Advisory Erlang", + "URL": "https://github.com/advisories?query=type%3Areviewed+ecosystem%3Aerlang" + }, + "Title": "Phoenix before 1.6.14 mishandles check_origin wildcarding", + "Description": "socket/transport.ex in Phoenix before 1.6.14 mishandles check_origin wildcarding. NOTE: LiveView applications are unaffected by default because of the presence of a LiveView CSRF token.", + "Severity": "HIGH", + "CVSS": { + "ghsa": { + "V3Vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N", + "V3Score": 7.5 + } + }, + "References": [ + "https://nvd.nist.gov/vuln/detail/CVE-2022-42975", + "https://github.com/phoenixframework/phoenix/commit/6e7185b33a59e0b1d1c0b4223adf340a73e963ae", + "https://hexdocs.pm/phoenix/1.6.14/changelog.html#1-6-14-2022-10-10", + "https://github.com/advisories/GHSA-p8f7-22gq-m7j9" + ], + "PublishedDate": "2022-10-17T12:00:27Z", + "LastModifiedDate": "2022-10-18T18:01:44Z" + } + ] + } + ] +} diff --git a/pkg/detector/library/driver.go b/pkg/detector/library/driver.go index 99f6e95135..585964136f 100644 --- a/pkg/detector/library/driver.go +++ b/pkg/detector/library/driver.go @@ -51,6 +51,9 @@ func NewDriver(libType string) (Driver, error) { case ftypes.Pipenv, ftypes.Poetry, ftypes.Pip, ftypes.PythonPkg: ecosystem = vulnerability.Pip comparer = pep440.Comparer{} + case ftypes.Hex: + ecosystem = vulnerability.Erlang + comparer = compare.GenericComparer{} case ftypes.Conan: ecosystem = vulnerability.Conan // Only semver can be used for version ranges diff --git a/pkg/fanal/analyzer/all/import.go b/pkg/fanal/analyzer/all/import.go index f6ea4bc7cd..9564f907cf 100644 --- a/pkg/fanal/analyzer/all/import.go +++ b/pkg/fanal/analyzer/all/import.go @@ -8,6 +8,7 @@ import ( _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language/c/conan" _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language/dotnet/deps" _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language/dotnet/nuget" + _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language/elixir/mix" _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language/golang/binary" _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language/golang/mod" _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language/java/gradle" diff --git a/pkg/fanal/analyzer/const.go b/pkg/fanal/analyzer/const.go index 218131ed87..46333e231c 100644 --- a/pkg/fanal/analyzer/const.go +++ b/pkg/fanal/analyzer/const.go @@ -74,6 +74,9 @@ const ( // C/C++ TypeConanLock Type = "conan-lock" + // Elixir + TypeMixLock Type = "mix-lock" + // Swift TypeCocoaPods Type = "cocoapods" @@ -128,14 +131,14 @@ var ( TypeBundler, TypeGemSpec, TypeCargo, TypeComposer, TypeJar, TypePom, TypeGradleLock, TypeNpmPkgLock, TypeNodePkg, TypeYarn, TypePnpm, TypeNuget, TypeDotNetCore, TypePythonPkg, TypePip, TypePipenv, TypePoetry, TypeGoBinary, TypeGoMod, TypeRustBinary, TypeConanLock, - TypeCocoaPods, + TypeCocoaPods, TypeMixLock, } // TypeLockfiles has all lock file analyzers TypeLockfiles = []Type{ TypeBundler, TypeNpmPkgLock, TypeYarn, TypePnpm, TypePip, TypePipenv, TypePoetry, TypeGoMod, TypePom, TypeConanLock, TypeGradleLock, - TypeCocoaPods, + TypeCocoaPods, TypeMixLock, } // TypeIndividualPkgs has all analyzers for individual packages diff --git a/pkg/fanal/analyzer/language/elixir/mix/mix.go b/pkg/fanal/analyzer/language/elixir/mix/mix.go new file mode 100644 index 0000000000..aae214b892 --- /dev/null +++ b/pkg/fanal/analyzer/language/elixir/mix/mix.go @@ -0,0 +1,49 @@ +package mix + +import ( + "context" + "os" + "path/filepath" + + "golang.org/x/xerrors" + + "github.com/aquasecurity/go-dep-parser/pkg/hex/mix" + "github.com/aquasecurity/trivy/pkg/fanal/analyzer" + "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language" + "github.com/aquasecurity/trivy/pkg/fanal/types" +) + +func init() { + analyzer.RegisterAnalyzer(&mixLockAnalyzer{}) +} + +const ( + version = 1 +) + +// mixLockAnalyzer analyzes 'mix.lock' +type mixLockAnalyzer struct{} + +func (a mixLockAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInput) (*analyzer.AnalysisResult, error) { + p := mix.NewParser() + res, err := language.Analyze(types.Hex, input.FilePath, input.Content, p) + if err != nil { + return nil, xerrors.Errorf("%s parse error: %w", input.FilePath, err) + } + return res, nil +} + +func (a mixLockAnalyzer) Required(filePath string, _ os.FileInfo) bool { + // Lock file name can be anything. + // cf. https://hexdocs.pm/mix/Mix.Project.html#module-configuration + // By default, we only check the default file name - `mix.lock`. + return filepath.Base(filePath) == types.MixLock +} + +func (a mixLockAnalyzer) Type() analyzer.Type { + return analyzer.TypeMixLock +} + +func (a mixLockAnalyzer) Version() int { + return version +} diff --git a/pkg/fanal/analyzer/language/elixir/mix/mix_test.go b/pkg/fanal/analyzer/language/elixir/mix/mix_test.go new file mode 100644 index 0000000000..000e7418b5 --- /dev/null +++ b/pkg/fanal/analyzer/language/elixir/mix/mix_test.go @@ -0,0 +1,89 @@ +package mix + +import ( + "github.com/aquasecurity/trivy/pkg/fanal/analyzer" + "github.com/aquasecurity/trivy/pkg/fanal/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "os" + "testing" +) + +func Test_mixLockAnalyzer_Analyze(t *testing.T) { + tests := []struct { + name string + inputFile string + want *analyzer.AnalysisResult + }{ + { + name: "happy path", + inputFile: "testdata/happy.mix.lock", + want: &analyzer.AnalysisResult{ + Applications: []types.Application{ + { + Type: types.Hex, + FilePath: "testdata/happy.mix.lock", + Libraries: []types.Package{ + { + ID: "bunt@0.2.0", + Name: "bunt", + Version: "0.2.0", + Locations: []types.Location{{StartLine: 2, EndLine: 2}}, + }, + }, + }, + }, + }, + }, + { + name: "empty file", + inputFile: "testdata/empty.mix.lock", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f, err := os.Open(tt.inputFile) + require.NoError(t, err) + defer func() { + err = f.Close() + assert.NoError(t, err) + }() + + a := mixLockAnalyzer{} + got, err := a.Analyze(nil, analyzer.AnalysisInput{ + FilePath: tt.inputFile, + Content: f, + }) + + assert.NoError(t, err) + assert.Equal(t, tt.want, got) + }) + } +} + +func Test_mixLockAnalyzer_Required(t *testing.T) { + tests := []struct { + name string + filePath string + want bool + }{ + { + name: "happy path", + filePath: "mix.lock", + want: true, + }, + { + name: "sad path", + filePath: "test.txt", + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + a := mixLockAnalyzer{} + got := a.Required(tt.filePath, nil) + assert.Equal(t, tt.want, got) + }) + } +} diff --git a/pkg/fanal/analyzer/language/elixir/mix/testdata/empty.mix.lock b/pkg/fanal/analyzer/language/elixir/mix/testdata/empty.mix.lock new file mode 100644 index 0000000000..1508128772 --- /dev/null +++ b/pkg/fanal/analyzer/language/elixir/mix/testdata/empty.mix.lock @@ -0,0 +1,2 @@ +%{ +} \ No newline at end of file diff --git a/pkg/fanal/analyzer/language/elixir/mix/testdata/happy.mix.lock b/pkg/fanal/analyzer/language/elixir/mix/testdata/happy.mix.lock new file mode 100644 index 0000000000..873a3a7fc7 --- /dev/null +++ b/pkg/fanal/analyzer/language/elixir/mix/testdata/happy.mix.lock @@ -0,0 +1,3 @@ +%{ + "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"}, +} \ No newline at end of file diff --git a/pkg/fanal/types/const.go b/pkg/fanal/types/const.go index 2ebac0647b..94f4de2c0b 100644 --- a/pkg/fanal/types/const.go +++ b/pkg/fanal/types/const.go @@ -30,6 +30,7 @@ const ( RustBinary = "rustbinary" Conan = "conan" Cocoapods = "cocoapods" + Hex = "hex" // Config files YAML = "yaml" @@ -73,4 +74,6 @@ const ( ConanLock = "conan.lock" CocoaPodsLock = "Podfile.lock" + + MixLock = "mix.lock" ) diff --git a/pkg/purl/purl.go b/pkg/purl/purl.go index 474ed67cc8..388183162e 100644 --- a/pkg/purl/purl.go +++ b/pkg/purl/purl.go @@ -96,6 +96,8 @@ func (p *PackageURL) PackageType() string { return ftypes.NuGet case packageurl.TypeSwift: return ftypes.Cocoapods + case packageurl.TypeHex: + return ftypes.Hex } return p.Type } @@ -308,6 +310,8 @@ func purlType(t string) string { return packageurl.TypeNPM case ftypes.Cocoapods: return packageurl.TypeSwift + case ftypes.Hex: + return packageurl.TypeHex case os.Alpine: return TypeAPK case os.Debian, os.Ubuntu: diff --git a/pkg/purl/purl_test.go b/pkg/purl/purl_test.go index b1d5871a9e..b21d732b9f 100644 --- a/pkg/purl/purl_test.go +++ b/pkg/purl/purl_test.go @@ -166,6 +166,23 @@ func TestNewPackageURL(t *testing.T) { }, }, }, + { + name: "hex package", + typ: ftypes.Hex, + pkg: ftypes.Package{ + ID: "bunt@0.2.0", + Name: "bunt", + Version: "0.2.0", + Locations: []ftypes.Location{{StartLine: 2, EndLine: 2}}, + }, + want: purl.PackageURL{ + PackageURL: packageurl.PackageURL{ + Type: packageurl.TypeHex, + Name: "bunt", + Version: "0.2.0", + }, + }, + }, { name: "os package", typ: os.RedHat, @@ -364,6 +381,18 @@ func TestFromString(t *testing.T) { }, }, }, + { + name: "happy path for hex", + purl: "pkg:hex/plug@1.14.0", + want: purl.PackageURL{ + PackageURL: packageurl.PackageURL{ + Type: packageurl.TypeHex, + Name: "plug", + Version: "1.14.0", + Qualifiers: packageurl.Qualifiers{}, + }, + }, + }, { name: "happy path for apk", purl: "pkg:apk/alpine/alpine-baselayout@3.2.0-r16?distro=3.14.2",