Use of pseudo-versioning for Go in Dependency Scanning
Some Go packages report advisories against a project's internal release versions but are not using version tags when publishing their package. This means that when this project is imported into another, go
will give it a pseudo version which is completely unrelated to the project's internal release versions.
Example:
cat go.mod
module gitlab.com/gitlab-org/security-products/tests/go-modules
# install latest of package
$ go get github.com/couchbase/sync_gateway
$ grep sync_gateway go.mod
github.com/couchbase/sync_gateway v0.0.0-20200108193823-e0ee69dd59b1 // indirect
# try installing affected version by using release semver
$ go get github.com/couchbase/sync_gateway@v2.1.2
go: finding github.com/couchbase/sync_gateway v2.1.2
go get github.com/couchbase/sync_gateway@v2.1.2: unknown revision v2.1.2
# install the affected version by using commit hash at release
$ go get github.com/couchbase/sync_gateway@35fe28e2c01c50335f26f7c757a8e5d127f61651
go: finding github.com/couchbase/sync_gateway 35fe28e2c01c50335f26f7c757a8e5d127f61651
[snip other lines]
$ grep sync_gateway go.mod
github.com/couchbase/sync_gateway v0.0.0-20181203170340-35fe28e2c01c
The version in go.mod
(35fe28e2c01c) will actually be the affected version documented in the advisory (2.1.2), but we wouldn't be able to match this. The version used by go
is not linked to the project's internal releases until they switch to go modules
and version their go.mod
appropriately.
Supporting the pseudo version, as well as the project-reported version, in gemnasium-db
may be the solution to this problem. There are two options we could explore:
- Use a separate field for advisories to store the pseudo-version ranges
- Use the
affected_range
advisory field to store the pseudo-version ranges
The second option seems preferable as it would not require any schema change. However, irrespective of the approach we are taking, there are some potential pitfalls we have to consider:
- Does
date(versionA) < date(versionB)
imply thatversionB > versionA
? If this is not guaranteed, we may run into problems when comparing two untagged versions where only the date can be used for comparisonv0.0.0-20181203170340-35fe28e2c01c>=v0.0.0-20181204170340-35fe28e2c01c
. - Could a release originate from a feature branch and what are the possible implications when it comes to version matching?
- Pseudo version used by Go do not adhere to the semver specification https://semver.org so we have to make sure that they can be properly processed by the analyzer.