Distinguish two vulnerabilities impacting the same dependency but with different versions
Summary
When Dependency Scanning finds the same vulnerabilities on two versions of the same package, we end up with the same CompareKey and location_fingerprint, so the two occurrences will be considered duplicates and deduped.
This is mainly an issue with NPM packages, other technologies often resolve dependencies to only one version per package.
The problem affects gemnasium and retire.js; they both rely on the DependencyScanningVulnerability.compareKey method to generate the compare key, and that method simply ignores the package version.
We could inject the package version in the compare key but then the vulnerability feedback would be invalidated whenever a dependency is upgraded, even if the new version is still affected by the same vulnerability. For instance, if a project depends on hawk v3.1.0 affected by CVE-2016-2515 and the vulnerability has been dismissed, it will come back and appear as new when the project upgrade to v3.1.1, which is also affected. Same goes for issues created from vulnerabilities.
Also, changing the way we forge the compare keys will result in loosing existing vulnerability feedback.
Steps to reproduce
Create a project with:
- package.json: https://gitlab.com/gitlab-org/security-products/tests/js-npm/blob/1b502aaf3fc2cfdc67b5adbfeb874811ca3b738e/package.json
- package-lock.json: https://gitlab.com/gitlab-org/security-products/tests/js-npm/blob/1b502aaf3fc2cfdc67b5adbfeb874811ca3b738e/package-lock.json
Run dependency scanning
Example Project
https://gitlab.com/gitlab-org/security-products/tests/js-npm
What is the current bug behavior?
Two vulnerabilities on different versions are reported as one vulnerability
What is the expected correct behavior?
Two vulnerabilities on different versions are reported as two separate vulnerabilities
Possible fixes
Track the ancestor(s) of the affected dependency in the scanners (gemnasium, retire.js), and inject them in the compare key. The change would be limited to npm. This is fairly complex. Also, gemnasium doesn't track the ancestor chain at the moment.
Alternatively, we could inject the package version in the compare key, resulting in the compare keys being more accurate (not merged) but less stable. Again, the change would be limited to npm.