feat(library): support a custom data source (#613)

* chore(mod): update trivy-db

* refactor(detector/library): use programming language instead of package
manager

* feat(library): add general advisory

* test(utils): add a util function initializing DB

* test(advisory): add tests

* chore: use aquasecurity/bolt-fixtures

* refactor: add comments

* chore(mod): revert fanal version

* chore(mod): update trivy-db

* refactor: update the comment
This commit is contained in:
Teppei Fukuda
2020-08-30 10:11:32 +03:00
committed by GitHub
parent ed8607b710
commit f50b0ce8af
10 changed files with 495 additions and 58 deletions

4
go.mod
View File

@@ -4,9 +4,10 @@ go 1.13
require (
github.com/Masterminds/semver/v3 v3.1.0
github.com/aquasecurity/bolt-fixtures v0.0.0-20200825112230-c0f517aea2ed
github.com/aquasecurity/fanal v0.0.0-20200820074632-6de62ef86882
github.com/aquasecurity/go-dep-parser v0.0.0-20190819075924-ea223f0ef24b
github.com/aquasecurity/trivy-db v0.0.0-20200816184446-3853f69c6e2f
github.com/aquasecurity/trivy-db v0.0.0-20200826140828-6da6467703aa
github.com/caarlos0/env/v6 v6.0.0
github.com/cenkalti/backoff v2.2.1+incompatible
github.com/cheggaaa/pb/v3 v3.0.3
@@ -20,7 +21,6 @@ require (
github.com/knqyf263/go-deb-version v0.0.0-20190517075300-09fca494f03d
github.com/knqyf263/go-rpm-version v0.0.0-20170716094938-74609b86c936
github.com/kylelemons/godebug v1.1.0
github.com/mattn/go-colorable v0.1.4 // indirect
github.com/olekukonko/tablewriter v0.0.2-0.20190607075207-195002e6e56a
github.com/open-policy-agent/opa v0.21.1
github.com/spf13/afero v1.2.2

38
go.sum
View File

@@ -50,14 +50,16 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/aquasecurity/bolt-fixtures v0.0.0-20200825112230-c0f517aea2ed h1:o6vSjobtDn634//l4yBCGCC2RWoRc4K5AUH8W8DZZds=
github.com/aquasecurity/bolt-fixtures v0.0.0-20200825112230-c0f517aea2ed/go.mod h1:eViGpgc5g/JGRHWUfVaNLFJQwXQOVWDDQ40c7uViyZU=
github.com/aquasecurity/fanal v0.0.0-20200820074632-6de62ef86882 h1:65VcAKqhkKwMpLr9Wz+wNnsk+U+lv+v/qfOK04uXT3E=
github.com/aquasecurity/fanal v0.0.0-20200820074632-6de62ef86882/go.mod h1:VP1+n6hMi6krpA0umEl0CkJp4hbg0R21kXWg0mjrekc=
github.com/aquasecurity/go-dep-parser v0.0.0-20190819075924-ea223f0ef24b h1:55Ulc/gvfWm4ylhVaR7MxOwujRjA6et7KhmUbSgUFf4=
github.com/aquasecurity/go-dep-parser v0.0.0-20190819075924-ea223f0ef24b/go.mod h1:BpNTD9vHfrejKsED9rx04ldM1WIbeyXGYxUrqTVwxVQ=
github.com/aquasecurity/testdocker v0.0.0-20200426142840-5f05bce6f12a h1:hsw7PpiymXP64evn/K7gsj3hWzMqLrdoeE6JkqDocVg=
github.com/aquasecurity/testdocker v0.0.0-20200426142840-5f05bce6f12a/go.mod h1:psfu0MVaiTDLpNxCoNsTeILSKY2EICBwv345f3M+Ffs=
github.com/aquasecurity/trivy-db v0.0.0-20200816184446-3853f69c6e2f h1:JGfRqWKDVAOiHXnoNMpLnipYi2sV527ML+ACLceNu+4=
github.com/aquasecurity/trivy-db v0.0.0-20200816184446-3853f69c6e2f/go.mod h1:e6VoIYR4u3gsi1aPxgvuuhqj+BCyAa1ytmhGHcw+TuA=
github.com/aquasecurity/trivy-db v0.0.0-20200826140828-6da6467703aa h1:v+ghkIw3D3qUP++M3e9XGkkoq59iZdCOT4uxj4l2pXs=
github.com/aquasecurity/trivy-db v0.0.0-20200826140828-6da6467703aa/go.mod h1:/uvzkPkLMA6ZM1M2uIODx5J7b1wYb/goJ34Nidcukaw=
github.com/aquasecurity/vuln-list-update v0.0.0-20191016075347-3d158c2bf9a2 h1:xbdUfr2KE4THsFx9CFWtWpU91lF+YhgP46moV94nYTA=
github.com/aquasecurity/vuln-list-update v0.0.0-20191016075347-3d158c2bf9a2/go.mod h1:6NhOP0CjZJL27bZZcaHECtzWdwDDm2g6yCY0QgXEGQQ=
github.com/araddon/dateparse v0.0.0-20190426192744-0d74ffceef83/go.mod h1:SLqhdZcd+dF3TEVL2RMoob5bBP5R1P1qkox+HtCBgGI=
@@ -146,6 +148,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
@@ -181,7 +185,11 @@ github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dp
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-redis/redis v6.15.7+incompatible h1:3skhDh95XQMpnqeqNftPkQD9jL9e5e36z/1SUm6dy1U=
github.com/go-redis/redis v6.15.7+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
@@ -189,6 +197,8 @@ github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/goccy/go-yaml v1.8.0 h1:WCe9sBiI0oZb6EC6f3kq3dv0+aEiNdstT7b4xxq4MJQ=
github.com/goccy/go-yaml v1.8.0/go.mod h1:wS4gNoLalDSJxo/SpngzPQ2BN4uuZVLCmbM4S3vd4+Y=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
@@ -306,6 +316,8 @@ github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LE
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@@ -316,12 +328,17 @@ github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcncea
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3mdw=
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-jsonpointer v0.0.0-20180225143300-37667080efed/go.mod h1:SDJ4hurDYyQ9/7nc+eCYtXqdufgK4Cq9TJlwPklqEYA=
github.com/mattn/go-runewidth v0.0.0-20181025052659-b20a3daf6a39/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
@@ -475,8 +492,8 @@ github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:
github.com/yashtewari/glob-intersection v0.0.0-20180916065949-5c77d914dd0b h1:vVRagRXf67ESqAb72hG2C/ZwI8NtJF2u2V76EsuOHGY=
github.com/yashtewari/glob-intersection v0.0.0-20180916065949-5c77d914dd0b/go.mod h1:HptNXiXVDcJjXe9SqMd0v2FsL9f8dz4GnXgltU6q/co=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg=
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
@@ -579,14 +596,17 @@ golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775 h1:TC0v2RSO1u2kn1ZugjrFXkRZAEaqMN/RW+OTZkBzmLE=
golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed h1:WBkVNH1zd9jg/dK4HCM4lNANnmd12EHC9z+LmcCG4ns=
golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8 h1:AvbQYmiaaaza3cW3QXRyPo5kYgpFIzOAfeAAN7m3qQ4=
golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -625,7 +645,6 @@ golang.org/x/tools v0.0.0-20200210192313-1ace956b0e17/go.mod h1:TB2adYChydJhpapK
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -667,8 +686,11 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/go-playground/validator.v9 v9.30.0 h1:Wk0Z37oBmKj9/n+tPyBHZmeL19LaCoK3Qq48VwYENss=
gopkg.in/go-playground/validator.v9 v9.30.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
@@ -683,11 +705,9 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@@ -0,0 +1,101 @@
package library
import (
"fmt"
"strings"
"github.com/Masterminds/semver/v3"
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy-db/pkg/db"
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
"github.com/aquasecurity/trivy/pkg/scanner/utils"
"github.com/aquasecurity/trivy/pkg/types"
)
// Advisory represents security advisories for each programming language
type Advisory struct {
lang string
comparer comparer
}
func NewAdvisory(lang string) *Advisory {
return &Advisory{
lang: lang,
comparer: newComparer(lang),
}
}
// DetectVulnerabilities scans buckets with the prefix according to the programming language in "Advisory".
// If "lang" is python, it looks for buckets with "python::" and gets security advisories from those buckets.
// It allows us to add a new data source with the lang prefix (e.g. python::new-data-source)
// and detect vulnerabilities without specifying a specific bucket name.
func (s *Advisory) DetectVulnerabilities(pkgName string, pkgVer *semver.Version) ([]types.DetectedVulnerability, error) {
// e.g. "python::"
prefix := fmt.Sprintf("%s::", s.lang)
advisories, err := db.Config{}.GetAdvisories(prefix, pkgName)
if err != nil {
return nil, xerrors.Errorf("failed to get %s advisories: %w", s.lang, err)
}
var vulns []types.DetectedVulnerability
for _, advisory := range advisories {
if !s.comparer.isVulnerable(pkgVer, advisory) {
continue
}
vuln := types.DetectedVulnerability{
VulnerabilityID: advisory.VulnerabilityID,
PkgName: pkgName,
InstalledVersion: pkgVer.String(),
FixedVersion: s.createFixedVersions(advisory),
}
vulns = append(vulns, vuln)
}
return vulns, nil
}
func (s *Advisory) createFixedVersions(advisory dbTypes.Advisory) string {
if len(advisory.PatchedVersions) != 0 {
return strings.Join(advisory.PatchedVersions, ", ")
}
var fixedVersions []string
for _, version := range advisory.VulnerableVersions {
for _, s := range strings.Split(version, ",") {
s = strings.TrimSpace(s)
if !strings.HasPrefix(s, "<=") && strings.HasPrefix(s, "<") {
s = strings.TrimPrefix(s, "<")
fixedVersions = append(fixedVersions, strings.TrimSpace(s))
}
}
}
return strings.Join(fixedVersions, ", ")
}
type comparer interface {
isVulnerable(pkgVer *semver.Version, advisory dbTypes.Advisory) bool
}
func newComparer(lang string) comparer {
switch lang {
// When another library is needed for version comparison, it can be added here.
}
return generalComparer{}
}
type generalComparer struct{}
func (c generalComparer) isVulnerable(pkgVer *semver.Version, advisory dbTypes.Advisory) bool {
if len(advisory.VulnerableVersions) != 0 {
return utils.MatchVersions(pkgVer, advisory.VulnerableVersions)
}
if utils.MatchVersions(pkgVer, advisory.PatchedVersions) ||
utils.MatchVersions(pkgVer, advisory.UnaffectedVersions) {
return false
}
return true
}

View File

@@ -0,0 +1,117 @@
package library_test
import (
"os"
"testing"
"github.com/Masterminds/semver/v3"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy-db/pkg/db"
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability"
"github.com/aquasecurity/trivy/pkg/detector/library"
"github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/pkg/utils"
)
func TestAdvisory_DetectVulnerabilities(t *testing.T) {
type fields struct {
lang string
}
type args struct {
pkgName string
pkgVer *semver.Version
}
tests := []struct {
name string
fixtures []string
fields fields
args args
want []types.DetectedVulnerability
wantErr string
}{
{
name: "happy path",
fixtures: []string{"testdata/fixtures/php.yaml"},
fields: fields{lang: vulnerability.PHP},
args: args{
pkgName: "symfony/symfony",
pkgVer: semver.MustParse("4.2.6"),
},
want: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2019-10909",
PkgName: "symfony/symfony",
InstalledVersion: "4.2.6",
FixedVersion: "4.2.7",
},
},
},
{
name: "no patched versions in the advisory",
fixtures: []string{"testdata/fixtures/php.yaml"},
fields: fields{lang: vulnerability.PHP},
args: args{
pkgName: "symfony/symfony",
pkgVer: semver.MustParse("4.4.6"),
},
want: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2020-5275",
PkgName: "symfony/symfony",
InstalledVersion: "4.4.6",
FixedVersion: "4.4.7",
},
},
},
{
name: "no vulnerable versions in the advisory",
fixtures: []string{"testdata/fixtures/ruby.yaml"},
fields: fields{lang: vulnerability.Ruby},
args: args{
pkgName: "activesupport",
pkgVer: semver.MustParse("4.1.1"),
},
want: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2015-3226",
PkgName: "activesupport",
InstalledVersion: "4.1.1",
FixedVersion: ">= 4.2.2, ~> 4.1.11",
},
},
},
{
name: "no vulnerability",
fixtures: []string{"testdata/fixtures/php.yaml"},
fields: fields{lang: vulnerability.PHP},
args: args{
pkgName: "symfony/symfony",
pkgVer: semver.MustParse("4.4.7"),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Initialize DB
dir := utils.InitTestDB(t, tt.fixtures)
defer os.RemoveAll(dir)
defer db.Close()
adv := library.NewAdvisory(tt.fields.lang)
got, err := adv.DetectVulnerabilities(tt.args.pkgName, tt.args.pkgVer)
switch {
case tt.wantErr != "":
require.NotNil(t, err)
assert.Contains(t, err.Error(), tt.wantErr)
default:
assert.NoError(t, err)
}
// Compare
assert.Equal(t, tt.want, got)
})
}
}

View File

@@ -4,8 +4,8 @@ import (
"fmt"
"github.com/Masterminds/semver/v3"
"github.com/aquasecurity/fanal/analyzer/library"
ecosystem "github.com/aquasecurity/trivy-db/pkg/vulnsrc/ghsa"
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability"
"github.com/aquasecurity/trivy/pkg/detector/library/bundler"
"github.com/aquasecurity/trivy/pkg/detector/library/cargo"
"github.com/aquasecurity/trivy/pkg/detector/library/composer"
@@ -31,19 +31,15 @@ func (d DriverFactory) NewDriver(filename string) (Driver, error) {
var driver Driver
switch filename {
case "Gemfile.lock":
driver = NewBundlerDriver()
driver = newRubyDriver()
case "Cargo.lock":
driver = NewCargoDriver()
driver = newRustDriver()
case "composer.lock":
driver = NewComposerDriver()
case "package-lock.json":
driver = NewNpmDriver()
case "yarn.lock":
driver = NewYarnDriver()
case "Pipfile.lock":
driver = NewPipenvDriver()
case "poetry.lock":
driver = NewPoetryDriver()
driver = newPHPDriver()
case "package-lock.json", "yarn.lock":
driver = newNodejsDriver()
case "Pipfile.lock", "poetry.lock":
driver = newPythonDriver()
default:
return Driver{}, xerrors.New(fmt.Sprintf("unsupport filename %s", filename))
}
@@ -51,18 +47,18 @@ func (d DriverFactory) NewDriver(filename string) (Driver, error) {
}
type Driver struct {
pkgManager string
lang string
advisories []advisory
}
func NewDriver(p string, advisories ...advisory) Driver {
return Driver{pkgManager: p, advisories: advisories}
func NewDriver(lang string, advisories ...advisory) Driver {
return Driver{lang: lang, advisories: advisories}
}
func (driver *Driver) Detect(pkgName string, pkgVer *semver.Version) ([]types.DetectedVulnerability, error) {
func (d *Driver) Detect(pkgName string, pkgVer *semver.Version) ([]types.DetectedVulnerability, error) {
var detectedVulnerabilities []types.DetectedVulnerability
uniqVulnIdMap := make(map[string]struct{})
for _, d := range driver.advisories {
for _, d := range append(d.advisories, NewAdvisory(d.lang)) {
vulns, err := d.DetectVulnerabilities(pkgName, pkgVer)
if err != nil {
return nil, xerrors.Errorf("failed to detect vulnerabilities: %w", err)
@@ -79,34 +75,26 @@ func (driver *Driver) Detect(pkgName string, pkgVer *semver.Version) ([]types.De
return detectedVulnerabilities, nil
}
func NewBundlerDriver() Driver {
return NewDriver(library.Bundler, ghsa.NewAdvisory(ecosystem.Rubygems), bundler.NewAdvisory())
}
func NewComposerDriver() Driver {
return NewDriver(library.Composer, ghsa.NewAdvisory(ecosystem.Composer), composer.NewAdvisory())
}
func NewCargoDriver() Driver {
return NewDriver(library.Cargo, cargo.NewAdvisory())
}
func NewNpmDriver() Driver {
return NewDriver(library.Npm, ghsa.NewAdvisory(ecosystem.Npm), node.NewAdvisory())
}
func NewYarnDriver() Driver {
return NewDriver(library.Yarn, ghsa.NewAdvisory(ecosystem.Npm), node.NewAdvisory())
}
func NewPipenvDriver() Driver {
return NewDriver(library.Pipenv, ghsa.NewAdvisory(ecosystem.Pip), python.NewAdvisory())
}
func NewPoetryDriver() Driver {
return NewDriver(library.Poetry, ghsa.NewAdvisory(ecosystem.Pip), python.NewAdvisory())
}
func (d *Driver) Type() string {
return d.pkgManager
return d.lang
}
func newRubyDriver() Driver {
return NewDriver(vulnerability.Ruby, ghsa.NewAdvisory(ecosystem.Rubygems), bundler.NewAdvisory())
}
func newPHPDriver() Driver {
return NewDriver(vulnerability.PHP, ghsa.NewAdvisory(ecosystem.Composer), composer.NewAdvisory())
}
func newRustDriver() Driver {
return NewDriver(vulnerability.Rust, cargo.NewAdvisory())
}
func newNodejsDriver() Driver {
return NewDriver(vulnerability.Nodejs, ghsa.NewAdvisory(ecosystem.Npm), node.NewAdvisory())
}
func newPythonDriver() Driver {
return NewDriver(vulnerability.Python, ghsa.NewAdvisory(ecosystem.Pip), python.NewAdvisory())
}

View File

@@ -0,0 +1,135 @@
package library_test
import (
"os"
"testing"
"github.com/Masterminds/semver/v3"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy-db/pkg/db"
"github.com/aquasecurity/trivy/pkg/detector/library"
"github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/pkg/utils"
)
func TestDriver_Detect(t *testing.T) {
type fields struct {
fileName string
}
type args struct {
pkgName string
pkgVer *semver.Version
}
tests := []struct {
name string
fixtures []string
fields fields
args args
want []types.DetectedVulnerability
wantErr string
}{
{
name: "happy path",
fixtures: []string{"testdata/fixtures/php.yaml"},
fields: fields{fileName: "composer.lock"},
args: args{
pkgName: "symfony/symfony",
pkgVer: semver.MustParse("4.2.6"),
},
want: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2019-10909",
PkgName: "symfony/symfony",
InstalledVersion: "4.2.6",
FixedVersion: "4.2.7",
},
},
},
{
name: "non-prefix buckets",
fixtures: []string{"testdata/fixtures/php-without-prefix.yaml"},
fields: fields{fileName: "composer.lock"},
args: args{
pkgName: "symfony/symfony",
pkgVer: semver.MustParse("4.2.6"),
},
want: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2019-10909",
PkgName: "symfony/symfony",
InstalledVersion: "4.2.6",
FixedVersion: "4.2.7",
},
},
},
{
name: "no patched versions in the advisory",
fixtures: []string{"testdata/fixtures/php.yaml"},
fields: fields{fileName: "composer.lock"},
args: args{
pkgName: "symfony/symfony",
pkgVer: semver.MustParse("4.4.6"),
},
want: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2020-5275",
PkgName: "symfony/symfony",
InstalledVersion: "4.4.6",
FixedVersion: "4.4.7",
},
},
},
{
name: "no vulnerable versions in the advisory",
fixtures: []string{"testdata/fixtures/ruby.yaml"},
fields: fields{fileName: "Gemfile.lock"},
args: args{
pkgName: "activesupport",
pkgVer: semver.MustParse("4.1.1"),
},
want: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2015-3226",
PkgName: "activesupport",
InstalledVersion: "4.1.1",
FixedVersion: ">= 4.2.2, ~> 4.1.11",
},
},
},
{
name: "no vulnerability",
fixtures: []string{"testdata/fixtures/php.yaml"},
fields: fields{fileName: "composer.lock"},
args: args{
pkgName: "symfony/symfony",
pkgVer: semver.MustParse("4.4.7"),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Initialize DB
dir := utils.InitTestDB(t, tt.fixtures)
defer os.RemoveAll(dir)
defer db.Close()
factory := library.DriverFactory{}
driver, err := factory.NewDriver(tt.fields.fileName)
require.NoError(t, err)
got, err := driver.Detect(tt.args.pkgName, tt.args.pkgVer)
switch {
case tt.wantErr != "":
require.NotNil(t, err)
assert.Contains(t, err.Error(), tt.wantErr)
default:
assert.NoError(t, err)
}
// Compare
assert.Equal(t, tt.want, got)
})
}
}

View File

@@ -0,0 +1,18 @@
- bucket: GitHub Security Advisory Composer
pairs:
- bucket: symfony/symfony
pairs:
- key: CVE-2019-10909
value:
PatchedVersions:
- 4.2.7
VulnerableVersions:
- ">= 4.2.0, < 4.2.7"
- bucket: php-security-advisories
pairs:
- bucket: symfony/symfony
pairs:
- key: CVE-2020-5275
value:
VulnerableVersions:
- ">= 4.4.0, < 4.4.7"

View File

@@ -0,0 +1,18 @@
- bucket: "php::GitHub Security Advisory Composer"
pairs:
- bucket: symfony/symfony
pairs:
- key: CVE-2019-10909
value:
PatchedVersions:
- 4.2.7
VulnerableVersions:
- ">= 4.2.0, < 4.2.7"
- bucket: "php::php-security-advisories"
pairs:
- bucket: symfony/symfony
pairs:
- key: CVE-2020-5275
value:
VulnerableVersions:
- ">= 4.4.0, < 4.4.7"

View File

@@ -0,0 +1,11 @@
- bucket: "ruby::ruby-advisory-db"
pairs:
- bucket: activesupport
pairs:
- key: CVE-2015-3226
value:
PatchedVersions:
- ">= 4.2.2"
- "~> 4.1.11"
UnaffectedVersions:
- "< 4.1.0"

View File

@@ -3,12 +3,18 @@ package utils
import (
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/stretchr/testify/require"
"golang.org/x/xerrors"
fixtures "github.com/aquasecurity/bolt-fixtures"
"github.com/aquasecurity/trivy-db/pkg/db"
"github.com/aquasecurity/trivy/pkg/log"
)
var cacheDir string
@@ -119,3 +125,26 @@ func CopyFile(src, dst string) (int64, error) {
n, err := io.Copy(destination, source)
return n, err
}
// InitTestDB is a utility function initializing BoltDB for unit testing
func InitTestDB(t *testing.T, fixtureFiles []string) string {
// Create a temp dir
dir, err := ioutil.TempDir("", "TestDB")
require.NoError(t, err)
dbPath := db.Path(dir)
dbDir := filepath.Dir(dbPath)
err = os.MkdirAll(dbDir, 0700)
require.NoError(t, err)
// Load testdata into BoltDB
loader, err := fixtures.New(dbPath, fixtureFiles)
require.NoError(t, err)
require.NoError(t, loader.Load())
require.NoError(t, loader.Close())
// Initialize DB
require.NoError(t, db.Init(dir))
return dir
}