Skip to content

Commit

Permalink
feat(java): add support for sbt projects using sbt-dependency-lock (#…
Browse files Browse the repository at this point in the history
…6882)

Signed-off-by: knqyf263 <knqyf263@gmail.com>
Co-authored-by: knqyf263 <knqyf263@gmail.com>
  • Loading branch information
stringbean and knqyf263 authored Jun 19, 2024
1 parent 1f8fca1 commit f18d035
Show file tree
Hide file tree
Showing 22 changed files with 687 additions and 5 deletions.
2 changes: 2 additions & 0 deletions docs/docs/configuration/reporting.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ The following languages are currently supported:
| PHP | [composer.lock][composer-lock] |
| Java | [pom.xml][pom-xml] |
| | [*gradle.lockfile][gradle-lockfile] |
| | [*.sbt.lock][sbt-lockfile] |
| Dart | [pubspec.lock][pubspec-lock] |

This tree is the reverse of the dependency graph.
Expand Down Expand Up @@ -447,5 +448,6 @@ $ trivy convert --format table --severity CRITICAL result.json
[composer-lock]: ../coverage/language/php.md#composer
[pom-xml]: ../coverage/language/java.md#pomxml
[gradle-lockfile]: ../coverage/language/java.md#gradlelock
[sbt-lockfile]: ../coverage/language/java.md#sbt
[pubspec-lock]: ../coverage/language/dart.md#dart
[cargo-binaries]: ../coverage/language/rust.md#binaries
1 change: 1 addition & 0 deletions docs/docs/coverage/language/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ On the other hand, when the target is a post-build artifact, like a container im
| [Java](java.md) | JAR/WAR/PAR/EAR[^4] ||| - | - |
| | pom.xml | - | - |||
| | *gradle.lockfile | - | - |||
| | *.sbt.lock | - | - |||
| [Go](golang.md) | Binaries built by Go ||| - | - |
| | go.mod | - | - |||
| [Rust](rust.md) | Cargo.lock |||||
Expand Down
16 changes: 14 additions & 2 deletions docs/docs/coverage/language/java.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Java
Trivy supports three types of Java scanning: `JAR/WAR/PAR/EAR`, `pom.xml` and `*gradle.lockfile` files.
Trivy supports four types of Java scanning: `JAR/WAR/PAR/EAR`, `pom.xml`, `*gradle.lockfile` and `*.sbt.lock` files.

Each artifact supports the following scanners:

Expand All @@ -8,6 +8,7 @@ Each artifact supports the following scanners:
| JAR/WAR/PAR/EAR ||| - |
| pom.xml ||||
| *gradle.lockfile ||||
| *.sbt.lock ||| - |

The following table provides an outline of the features Trivy offers.

Expand All @@ -16,6 +17,7 @@ The following table provides an outline of the features Trivy offers.
| JAR/WAR/PAR/EAR | Trivy Java DB | Include | - | - |
| pom.xml | Maven repository [^1] | Exclude ||[^7] |
| *gradle.lockfile | - | Exclude |||
| *.sbt.lock | - | Exclude | - ||

These may be enabled or disabled depending on the target.
See [here](./index.md) for the detail.
Expand Down Expand Up @@ -94,6 +96,15 @@ Trity also can detect licenses for dependencies.

Make sure that you have cache[^8] directory to find licenses from `*.pom` dependency files.


## SBT

`build.sbt.lock` files only contain information about used dependencies. This requires a lockfile generated using the
[sbt-dependency-lock][sbt-dependency-lock] plugin.

!!!note
All necessary files are checked locally. SBT file scanning doesn't require internet access.

[^1]: Uses maven repository to get information about dependencies. Internet access required.
[^2]: It means `*.jar`, `*.war`, `*.par` and `*.ear` file
[^3]: `ArtifactID`, `GroupID` and `Version`
Expand All @@ -106,4 +117,5 @@ Make sure that you have cache[^8] directory to find licenses from `*.pom` depend
[dependency-graph]: ../../configuration/reporting.md#show-origins-of-vulnerable-dependencies
[maven-invoker-plugin]: https://maven.apache.org/plugins/maven-invoker-plugin/usage.html
[maven-central]: https://repo.maven.apache.org/maven2/
[maven-pom-repos]: https://maven.apache.org/settings.html#repositories
[maven-pom-repos]: https://maven.apache.org/settings.html#repositories
[sbt-dependency-lock]: https://stringbean.github.io/sbt-dependency-lock
8 changes: 8 additions & 0 deletions integration/repo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,14 @@ func TestRepository(t *testing.T) {
},
golden: "testdata/gradle.json.golden",
},
{
name: "sbt",
args: args{
scanner: types.VulnerabilityScanner,
input: "testdata/fixtures/repo/sbt",
},
golden: "testdata/sbt.json.golden",
},
{
name: "conan",
args: args{
Expand Down
29 changes: 29 additions & 0 deletions integration/testdata/fixtures/repo/sbt/build.sbt.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"lockVersion" : 1,
"timestamp" : "2024-06-06T11:03:09.964557Z",
"configurations" : [
"compile",
"optional",
"provided",
"runtime",
"test"
],
"dependencies" : [
{
"org" : "com.fasterxml.jackson.core",
"name" : "jackson-databind",
"version" : "2.9.1",
"artifacts" : [
{
"name" : "jackson-databind.jar",
"hash" : "sha1:716da1830a2043f18882fc036ec26eb32cbe5aff"
}
],
"configurations" : [
"compile",
"runtime",
"test"
]
}
]
}
149 changes: 149 additions & 0 deletions integration/testdata/sbt.json.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactName": "testdata/fixtures/repo/sbt",
"ArtifactType": "repository",
"Metadata": {
"ImageConfig": {
"architecture": "",
"created": "0001-01-01T00:00:00Z",
"os": "",
"rootfs": {
"type": "",
"diff_ids": null
},
"config": {}
}
},
"Results": [
{
"Target": "build.sbt.lock",
"Class": "lang-pkgs",
"Type": "sbt",
"Vulnerabilities": [
{
"VulnerabilityID": "CVE-2020-9548",
"PkgID": "com.fasterxml.jackson.core:jackson-databind:2.9.1",
"PkgName": "com.fasterxml.jackson.core:jackson-databind",
"PkgIdentifier": {
"PURL": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.9.1",
"UID": "9ccd2eb3e03373ff"
},
"InstalledVersion": "2.9.1",
"FixedVersion": "2.9.10.4",
"Status": "fixed",
"Layer": {},
"SeveritySource": "ghsa",
"PrimaryURL": "https://avd.aquasec.com/nvd/cve-2020-9548",
"DataSource": {
"ID": "ghsa",
"Name": "GitHub Security Advisory Maven",
"URL": "https://github.com/advisories?query=type%3Areviewed+ecosystem%3Amaven"
},
"Title": "jackson-databind: Serialization gadgets in anteros-core",
"Description": "FasterXML jackson-databind 2.x before 2.9.10.4 mishandles the interaction between serialization gadgets and typing, related to br.com.anteros.dbcp.AnterosDBCPConfig (aka anteros-core).",
"Severity": "CRITICAL",
"CweIDs": [
"CWE-502"
],
"VendorSeverity": {
"ghsa": 4,
"nvd": 4,
"redhat": 3
},
"CVSS": {
"nvd": {
"V2Vector": "AV:N/AC:M/Au:N/C:P/I:P/A:P",
"V3Vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
"V2Score": 6.8,
"V3Score": 9.8
},
"redhat": {
"V3Vector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H",
"V3Score": 8.1
}
},
"References": [
"https://access.redhat.com/security/cve/CVE-2020-9548",
"https://github.com/FasterXML/jackson-databind/issues/2634",
"https://github.com/advisories/GHSA-p43x-xfjf-5jhr",
"https://lists.apache.org/thread.html/r35d30db00440ef63b791c4b7f7acb036e14d4a23afa2a249cb66c0fd@%3Cissues.zookeeper.apache.org%3E",
"https://lists.apache.org/thread.html/r9464a40d25c3ba1a55622db72f113eb494a889656962d098c70c5bb1@%3Cdev.zookeeper.apache.org%3E",
"https://lists.apache.org/thread.html/r98c9b6e4c9e17792e2cd1ec3e4aa20b61a791939046d3f10888176bb@%3Cissues.zookeeper.apache.org%3E",
"https://lists.apache.org/thread.html/rb6fecb5e96a6d61e175ff49f33f2713798dd05cf03067c169d195596@%3Cissues.zookeeper.apache.org%3E",
"https://lists.apache.org/thread.html/rd5a4457be4623038c3989294429bc063eec433a2e55995d81591e2ca@%3Cissues.zookeeper.apache.org%3E",
"https://lists.apache.org/thread.html/rdd49ab9565bec436a896bc00c4b9fc9dce1598e106c318524fbdfec6@%3Cissues.zookeeper.apache.org%3E",
"https://lists.apache.org/thread.html/rdd4df698d5d8e635144d2994922bf0842e933809eae259521f3b5097@%3Cissues.zookeeper.apache.org%3E",
"https://lists.apache.org/thread.html/rf1bbc0ea4a9f014cf94df9a12a6477d24a27f52741dbc87f2fd52ff2@%3Cissues.geode.apache.org%3E",
"https://lists.debian.org/debian-lts-announce/2020/03/msg00008.html",
"https://medium.com/@cowtowncoder/on-jackson-cves-dont-panic-here-is-what-you-need-to-know-54cd0d6e8062",
"https://nvd.nist.gov/vuln/detail/CVE-2020-9548",
"https://security.netapp.com/advisory/ntap-20200904-0006/",
"https://www.oracle.com/security-alerts/cpujan2021.html",
"https://www.oracle.com/security-alerts/cpujul2020.html",
"https://www.oracle.com/security-alerts/cpuoct2020.html",
"https://www.oracle.com/security-alerts/cpuoct2021.html"
],
"PublishedDate": "2020-03-02T04:15:00Z",
"LastModifiedDate": "2021-12-02T21:23:00Z"
},
{
"VulnerabilityID": "CVE-2021-20190",
"PkgID": "com.fasterxml.jackson.core:jackson-databind:2.9.1",
"PkgName": "com.fasterxml.jackson.core:jackson-databind",
"PkgIdentifier": {
"PURL": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.9.1",
"UID": "9ccd2eb3e03373ff"
},
"InstalledVersion": "2.9.1",
"FixedVersion": "2.9.10.7",
"Status": "fixed",
"Layer": {},
"SeveritySource": "nvd",
"PrimaryURL": "https://avd.aquasec.com/nvd/cve-2021-20190",
"DataSource": {
"ID": "glad",
"Name": "GitLab Advisory Database Community",
"URL": "https://gitlab.com/gitlab-org/advisories-community"
},
"Title": "jackson-databind: mishandles the interaction between serialization gadgets and typing, related to javax.swing",
"Description": "A flaw was found in jackson-databind before 2.9.10.7. FasterXML mishandles the interaction between serialization gadgets and typing. The highest threat from this vulnerability is to data confidentiality and integrity as well as system availability.",
"Severity": "HIGH",
"CweIDs": [
"CWE-502"
],
"VendorSeverity": {
"ghsa": 3,
"nvd": 3,
"redhat": 3
},
"CVSS": {
"nvd": {
"V2Vector": "AV:N/AC:M/Au:N/C:P/I:P/A:C",
"V3Vector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H",
"V2Score": 8.3,
"V3Score": 8.1
},
"redhat": {
"V3Vector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H",
"V3Score": 8.1
}
},
"References": [
"https://access.redhat.com/security/cve/CVE-2021-20190",
"https://bugzilla.redhat.com/show_bug.cgi?id=1916633",
"https://github.com/FasterXML/jackson-databind/commit/7dbf51bf78d157098074a20bd9da39bd48c18e4a",
"https://github.com/FasterXML/jackson-databind/issues/2854",
"https://github.com/advisories/GHSA-5949-rw7g-wx7w",
"https://lists.apache.org/thread.html/r380e9257bacb8551ee6fcf2c59890ae9477b2c78e553fa9ea08e9d9a@%3Ccommits.nifi.apache.org%3E",
"https://lists.debian.org/debian-lts-announce/2021/04/msg00025.html",
"https://nvd.nist.gov/vuln/detail/CVE-2021-20190",
"https://security.netapp.com/advisory/ntap-20210219-0008/"
],
"PublishedDate": "2021-01-19T17:15:00Z",
"LastModifiedDate": "2021-07-20T23:15:00Z"
}
]
}
]
}
2 changes: 1 addition & 1 deletion pkg/dependency/id.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func ID(ltype types.LangType, name, version string) string {
if !strings.HasPrefix(version, "v") {
version = "v" + version
}
case types.Jar, types.Pom, types.Gradle:
case types.Jar, types.Pom, types.Gradle, types.Sbt:
sep = ":"
}
return name + sep + version
Expand Down
9 changes: 9 additions & 0 deletions pkg/dependency/id_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ func TestID(t *testing.T) {
},
want: "test:1.0.0",
},
{
name: "sbt",
args: args{
ltype: types.Sbt,
name: "test",
version: "1.0.0",
},
want: "test:1.0.0",
},
{
name: "pip",
args: args{
Expand Down
84 changes: 84 additions & 0 deletions pkg/dependency/parser/sbt/lockfile/parse.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package lockfile

import (
"io"
"slices"
"sort"

"github.com/liamg/jfather"
"golang.org/x/xerrors"

"github.com/aquasecurity/trivy/pkg/dependency"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
xio "github.com/aquasecurity/trivy/pkg/x/io"
)

// lockfile format defined at: https://stringbean.github.io/sbt-dependency-lock/file-formats/version-1.html
type sbtLockfile struct {
Version int `json:"lockVersion"`
Dependencies []sbtLockfileDependency `json:"dependencies"`
}

type sbtLockfileDependency struct {
Organization string `json:"org"`
Name string `json:"name"`
Version string `json:"version"`
Configurations []string `json:"configurations"`
StartLine int
EndLine int
}

type Parser struct{}

func NewParser() *Parser {
return &Parser{}
}

func (Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
var lockfile sbtLockfile
input, err := io.ReadAll(r)

if err != nil {
return nil, nil, xerrors.Errorf("failed to read sbt lockfile: %w", err)
}
if err := jfather.Unmarshal(input, &lockfile); err != nil {
return nil, nil, xerrors.Errorf("JSON decoding failed: %w", err)
}

var libraries ftypes.Packages

for _, dep := range lockfile.Dependencies {
if slices.ContainsFunc(dep.Configurations, isIncludedConfig) {
name := dep.Organization + ":" + dep.Name
libraries = append(libraries, ftypes.Package{
ID: dependency.ID(ftypes.Sbt, name, dep.Version),
Name: name,
Version: dep.Version,
Locations: []ftypes.Location{
{
StartLine: dep.StartLine,
EndLine: dep.EndLine,
},
},
})
}
}

sort.Sort(libraries)
return libraries, nil, nil
}

// UnmarshalJSONWithMetadata needed to detect start and end lines of deps
func (t *sbtLockfileDependency) UnmarshalJSONWithMetadata(node jfather.Node) error {
if err := node.Decode(&t); err != nil {
return err
}
// Decode func will overwrite line numbers if we save them first
t.StartLine = node.Range().Start.Line
t.EndLine = node.Range().End.Line
return nil
}

func isIncludedConfig(config string) bool {
return config == "compile" || config == "runtime"
}
Loading

0 comments on commit f18d035

Please sign in to comment.