Repository: google/osv-scanner
Pull request #649 (2023-11-08 02:58:13)

Don't include nested vendored libs in determineversions query.
This mirrors https://github.com/google/osv.dev/commit/81a02135365a8ff0856588cf844645ed253b5257.

codecov-commenter: ## [Codecov](https://app.codecov.io/gh/google/osv-scanner/pull/649?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) Report
> Merging [#649](https://app.codecov.io/gh/google/osv-scanner/pull/649?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) (826a3a7) into [main](https://app.codecov.io/gh/google/osv-scanner/commit/8fef787274901c2a7f4d4acf3ee6931079218993?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) (8fef787) will **decrease** coverage by `0.06%`.
> The diff coverage is `0.00%`.

```diff
@@            Coverage Diff             @@
##             main     #649      +/-   ##
==========================================
- Coverage   79.05%   79.00%   -0.06%     
==========================================
  Files          79       79              
  Lines        5758     5762       +4     
==========================================
  Hits         4552     4552              
- Misses       1015     1019       +4     
  Partials      191      191              
```


| [Files](https://app.codecov.io/gh/google/osv-scanner/pull/649?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) | Coverage Δ | |
|---|---|---|
| [pkg/osvscanner/osvscanner.go](https://app.codecov.io/gh/google/osv-scanner/pull/649?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google#diff-cGtnL29zdnNjYW5uZXIvb3N2c2Nhbm5lci5nbw==) | `55.14% <0.00%> (-0.35%)` | :arrow_down: |



Patch:
diff --git a/.golangci.yaml b/.golangci.yaml
index 8e21412..ad85722 100644
--- a/.golangci.yaml
+++ b/.golangci.yaml
@@ -30,7 +30,7 @@ linters:
     - testpackage      # will re-add later (another-rex)
     - goerr113         # will re-add later (another-rex)
     - nonamedreturns   # disagree with, for now (another-rex)
-    - depguard         # not necessary at the moment (another-rex)
+    - goconst          # not everything should be a constant
   presets:
     - bugs
     - comment
@@ -42,6 +42,16 @@ linters:
     - unused
 
 linters-settings:
+  depguard:
+    rules:
+      regexp:
+        files:
+          - '!**/internal/cachedregexp/**'
+          - '!**/main_test.go'
+        deny:
+          - pkg: 'regexp'
+            desc:
+              'Use github.com/google/osv-scanner/internal/cachedregexp instead'
   gocritic:
     disabled-checks:
       - ifElseChain
diff --git a/Dockerfile b/Dockerfile
index fc6d330..4096af5 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-FROM golang:alpine@sha256:926f7f7e1ab8509b4e91d5ec6d5916ebb45155b0c8920291ba9f361d65385806 AS builder
+FROM golang:alpine@sha256:110b07af87238fbdc5f1df52b00927cf58ce3de358eeeb1854f10a8b5e5e1411 AS builder
 
 WORKDIR /src
 COPY ./go.mod ./go.sum ./
diff --git a/action.dockerfile b/action.dockerfile
index d90fe41..dda22da 100644
--- a/action.dockerfile
+++ b/action.dockerfile
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-FROM golang:alpine@sha256:926f7f7e1ab8509b4e91d5ec6d5916ebb45155b0c8920291ba9f361d65385806
+FROM golang:alpine@sha256:110b07af87238fbdc5f1df52b00927cf58ce3de358eeeb1854f10a8b5e5e1411
 
 RUN mkdir /src
 WORKDIR /src
diff --git a/codecov.yml b/codecov.yml
deleted file mode 100644
index 63ee507..0000000
--- a/codecov.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-ignore:
-  - internal/testutility
\ No newline at end of file
diff --git a/docs/Gemfile b/docs/Gemfile
index 0bffcee..62e7b09 100644
--- a/docs/Gemfile
+++ b/docs/Gemfile
@@ -14,7 +14,7 @@ source "https://rubygems.org"
 gem "github-pages", "~> 228", group: :jekyll_plugins
 # If you have any plugins, put them here!
 group :jekyll_plugins do
-  gem "jekyll-feed", "~> 0.17"
+  gem "jekyll-feed", "~> 0.15"
 end
 
 # Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem
diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock
index ca4d259..8293108 100644
--- a/docs/Gemfile.lock
+++ b/docs/Gemfile.lock
@@ -1,14 +1,20 @@
 GEM
   remote: https://rubygems.org/
   specs:
-    activesupport (7.0.8)
+    activesupport (7.1.1)
+      base64
+      bigdecimal
       concurrent-ruby (~> 1.0, >= 1.0.2)
+      connection_pool (>= 2.2.5)
+      drb
       i18n (>= 1.6, < 2)
       minitest (>= 5.1)
+      mutex_m
       tzinfo (~> 2.0)
     addressable (2.8.5)
       public_suffix (>= 2.0.2, < 6.0)
-    base64 (0.1.1)
+    base64 (0.2.0)
+    bigdecimal (3.1.4)
     coffee-script (2.4.1)
       coffee-script-source
       execjs
@@ -16,8 +22,11 @@ GEM
     colorator (1.1.0)
     commonmarker (0.23.10)
     concurrent-ruby (1.2.2)
+    connection_pool (2.4.1)
     dnsruby (1.70.0)
       simpleidn (~> 0.2.1)
+    drb (2.2.0)
+      ruby2_keywords
     em-websocket (0.5.3)
       eventmachine (>= 0.12.9)
       http_parser.rb (~> 0)
@@ -212,6 +221,7 @@ GEM
       jekyll-feed (~> 0.9)
       jekyll-seo-tag (~> 2.1)
     minitest (5.20.0)
+    mutex_m (0.2.0)
     nokogiri (1.15.4-x86_64-linux)
       racc (~> 1.4)
     octokit (4.25.1)
@@ -220,7 +230,7 @@ GEM
     pathutil (0.16.2)
       forwardable-extended (~> 2.6)
     public_suffix (4.0.7)
-    racc (1.7.1)
+    racc (1.7.3)
     rb-fsevent (0.11.2)
     rb-inotify (0.10.1)
       ffi (~> 1.0)
@@ -257,7 +267,7 @@ PLATFORMS
 DEPENDENCIES
   github-pages (~> 228)
   http_parser.rb (~> 0.8.0)
-  jekyll-feed (~> 0.12)
+  jekyll-feed (~> 0.15)
   tzinfo (>= 1, < 3)
   tzinfo-data
   wdm (~> 0.1.1)
diff --git a/docs/configuration.md b/docs/configuration.md
index b4b0cc6..aece78f 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -2,7 +2,7 @@
 layout: page
 title: Configuration
 permalink: /configuration/
-nav_order: 4
+nav_order: 5
 ---
 # Configure OSV-Scanner
 
diff --git a/docs/contribute.md b/docs/contribute.md
index a12cb39..7ab7823 100644
--- a/docs/contribute.md
+++ b/docs/contribute.md
@@ -2,7 +2,7 @@
 layout: page
 title: Contribute
 permalink: /contribute/
-nav_order: 8
+nav_order: 9
 ---
 # Contribute
 
diff --git a/docs/experimental.md b/docs/experimental.md
index 0d1d801..bb2b77e 100644
--- a/docs/experimental.md
+++ b/docs/experimental.md
@@ -2,7 +2,7 @@
 layout: page
 title: Experimental Features
 permalink: /experimental/
-nav_order: 7
+nav_order: 8
 ---
 # Experimental Features
 
diff --git a/docs/github-action.md b/docs/github-action.md
index 7dee78e..601b71f 100644
--- a/docs/github-action.md
+++ b/docs/github-action.md
@@ -2,7 +2,7 @@
 layout: page
 title: GitHub Action
 permalink: /github-action/
-nav_order: 6
+nav_order: 7
 ---
 
 # GitHub Action
diff --git a/docs/index.md b/docs/index.md
index 5be8477..c6be03d 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -22,4 +22,4 @@ OSV-Scanner provides an officially supported frontend to the [OSV database](http
 
 The above all results in fewer, more actionable vulnerability notifications, which reduces the time needed to resolve them. Check out our [announcement blog post] for more details!
 
-[announcement blog post]: https://security.googleblog.com/2022/12/announcing-osv-scanner-vulnerability.html
+[announcement blog post]: https://security.googleblog.com/2022/12/announcing-osv-scanner-vulnerability.html
\ No newline at end of file
diff --git a/docs/installation.md b/docs/installation.md
index e7489b1..2f37752 100644
--- a/docs/installation.md
+++ b/docs/installation.md
@@ -2,7 +2,7 @@
 layout: page
 title: Installation
 permalink: /installation/
-nav_order: 2
+nav_order: 3
 ---
 
 # Installation
diff --git a/docs/output.md b/docs/output.md
index 9c56955..d1c8deb 100644
--- a/docs/output.md
+++ b/docs/output.md
@@ -2,7 +2,7 @@
 layout: page
 title: Output
 permalink: /output/
-nav_order: 5
+nav_order: 6
 ---
 # Output
 {: .no_toc }
diff --git a/docs/supported_languages_and_lockfiles.md b/docs/supported_languages_and_lockfiles.md
new file mode 100644
index 0000000..cdc6734
--- /dev/null
+++ b/docs/supported_languages_and_lockfiles.md
@@ -0,0 +1,105 @@
+---
+layout: page
+title: Supported Languages and Lockfiles
+permalink: /supported-languages-and-lockfiles/
+nav_order: 2
+---
+
+# Supported Languages and Lockfiles
+
+{: .no_toc }
+
+<details open markdown="block">
+  <summary>
+    Table of contents
+  </summary>
+  {: .text-delta }
+- TOC
+{:toc}
+</details>
+
+## Supported lockfiles
+
+A wide range of lockfiles are supported by utilizing this [lockfile package](https://github.com/google/osv-scanner/tree/main/pkg/lockfile).
+
+|  Language  | Compatible Lockfile(s) |
+|:-----------|:------------------|
+| C/C++ | `conan.lock`<br>[C/C++ commit scanning](#cc-scanning)|
+| Dart | `pubspec.lock`|
+| Elixir | `mix.lock` |
+| Go | `go.mod` |
+| Java | `buildscript-gradle.lockfile`<br>`gradle.lockfile`<br>`pom.xml`[\*](https://github.com/google/osv-scanner/issues/35) |
+| Javascript | `package-lock.json`<br>`pnpm-lock.yaml`<br>`yarn.lock`|
+| PHP        | `composer.lock`|
+| Python     | `Pipfile.lock`<br>`poetry.lock`<br>`requirements.txt`[\*](https://github.com/google/osv-scanner/issues/34) |
+| Ruby       | `Gemfile.lock`|
+| Rust       | `Cargo.lock`|
+
+## Alpine Package Keeper and Debian Package Keeper
+
+The scanner also supports:
+- `installed` files used by the Alpine Package Keeper (apk) that typically live at `/lib/apk/db/installed`
+- `status` files used by the Debian Package manager (dpkg) that typically live at `/var/lib/dpkg/status`
+
+however you must [specify](./usage.md/#specify-lockfiles) them explicitly using the `--lockfile` flag:
+
+```bash
+osv-scanner --lockfile 'apk-installed:/lib/apk/db/installed'
+osv-scanner --lockfile 'dpkg-status:/var/lib/dpkg/status'
+```
+
+## C/C++ scanning
+
+With the addition of [vulnerable commit ranges](https://osv.dev/blog/posts/introducing-broad-c-c++-support/) to the OSV.dev database, OSV-Scanner now supports vendored and submoduled C/C++ dependencies 
+
+Because the C/C++ ecosystem does not have a centralized package manager, C/C++ dependencies tend to be bundled with the project. Dependencies are either [submoduled](#submoduled-dependencies) or [vendored](#vendored-dependencies). In either case, OSV-Scanner is able to find known vulnerabilities in your project dependencies. 
+
+OSV-Scanner's C/C++ support is based on commit-level data. OSV's commit-level data covers the majority of C/C++ vulnerabilities within the OSV database, but users should be aware that there may be vulnerabilities in their dependencies that could be excluded from OSV-Scanner results. Adding more commit-level data to the database is an ongoing project. 
+
+### Submoduled dependencies
+
+Submoduled dependencies are included in the project folder retain their Git histories. To scan a C/C++ project with submoduled dependencies:
+
+1. Navigate to the root folder of your project. 
+2. Ensure that your submodules are up to date using `git submodule update`. 
+3. Run scanner using `osv-scanner -r .`. 
+
+### Vendored dependencies
+
+Vendored dependencies have been directly copied into the project folder, but do not retain their Git histories. OSV-Scanner uses OSV's [determineversion API](https://google.github.io/osv.dev/post-v1-determineversion/) to estimate each dependency's version (and associated Git Commit). Vulnerabilities for the estimated version are returned. This process requires no additional work from the user. Run OSV-Scanner as you normally would. 
+
+## Custom Lockfiles
+
+If you have a custom lockfile that we do not support or prefer to do your own custom parsing, you can extract the custom lockfile information and create a custom intermediate file containing dependency information so that osv-scanner can still check for vulnerabilities.
+
+Once you extracted your own dependency information, place it in a `osv-scanner.json` file, with the same format as the JSON output of osv-scanner, e.g.:
+
+```
+{
+  "results": [
+    {
+      "packages": [
+        {
+          "package": {
+            "name": "github.com/repo/url",
+            "commit": "9a6bd55c9d0722cb101fe85a3b22d89e4ff4fe52"
+          }
+        },
+        {
+          "package": {
+            "name": "react",
+            "version": "1.2.3",
+            "ecosystem": "npm"
+          }
+        },
+        // ...
+      ]
+    }
+  ]
+}
+```
+
+Then pass this to `osv-scanner` with this:
+```
+osv-scanner --lockfile osv-scanner:/path/to/osv-scanner.json
+```
\ No newline at end of file
diff --git a/docs/usage.md b/docs/usage.md
index e907cc2..db8619e 100644
--- a/docs/usage.md
+++ b/docs/usage.md
@@ -2,7 +2,7 @@
 layout: page
 title: Usage
 permalink: /usage/
-nav_order: 3
+nav_order: 4
 ---
 # Usage
 
@@ -69,36 +69,7 @@ It is possible to specify more than one lockfile at a time; you can also specify
 osv-scanner --lockfile 'requirements.txt:/path/to/your/extra-requirements.txt'
 ```
 
-A wide range of lockfiles are supported by utilizing this [lockfile package](https://github.com/google/osv-scanner/tree/main/pkg/lockfile). This is the current list of supported lockfiles:
-
-- `buildscript-gradle.lockfile`
-- `Cargo.lock`
-- `composer.lock`
-- `conan.lock`
-- `Gemfile.lock`
-- `go.mod`
-- `gradle.lockfile`
-- `mix.lock`
-- `package-lock.json`
-- `packages.lock.json`
-- `Pipfile.lock`
-- `pnpm-lock.yaml`
-- `poetry.lock`
-- `pom.xml`[\*](https://github.com/google/osv-scanner/issues/35)
-- `pubspec.lock`
-- `requirements.txt`[\*](https://github.com/google/osv-scanner/issues/34)
-- `yarn.lock`
-
-The scanner also supports:
-- `installed` files used by the Alpine Package Keeper (apk) that typically live at `/lib/apk/db/installed`
-- `status` files used by the Debian Package manager (dpkg) that typically live at `/var/lib/dpkg/status`
-
-however you must specify them explicitly using the `--lockfile` flag:
-
-```bash
-osv-scanner --lockfile 'apk-installed:/lib/apk/db/installed'
-osv-scanner --lockfile 'dpkg-status:/var/lib/dpkg/status'
-```
+The list of supported lockfile formats can be found [here](/osv-scanner/supported-languages-and-lockfiles/).
 
 If the file you are scanning is located in a directory that has a colon in its name,
 you can prefix the path to just a colon to explicitly signal to the scanner that
@@ -108,42 +79,6 @@ it should infer the parser based on the filename:
 osv-scanner --lockfile ':/path/to/my:projects/package-lock.json'
 ```
 
-### Custom Lockfiles
-
-If you have a custom lockfile that we do not support or prefer to do your own custom parsing, you can extract the custom lockfile information and create a custom intermediate file containing dependency information so that osv-scanner can still check for vulnerabilities.
-
-Once you extracted your own dependency information, place it in a `osv-scanner.json` file, with the same format as the JSON output of osv-scanner, e.g.:
-
-```
-{
-  "results": [
-    {
-      "packages": [
-        {
-          "package": {
-            "name": "github.com/repo/url",
-            "commit": "9a6bd55c9d0722cb101fe85a3b22d89e4ff4fe52"
-          }
-        },
-        {
-          "package": {
-            "name": "react",
-            "version": "1.2.3",
-            "ecosystem": "npm"
-          }
-        },
-        // ...
-      ]
-    }
-  ]
-}
-```
-
-Then pass this to `osv-scanner` with this:
-```
-osv-scanner --lockfile osv-scanner:/path/to/osv-scanner.json
-```
-
 ## Scanning a Debian based docker image packages
 Preview
 {: .label }
@@ -190,3 +125,23 @@ The `--output` flag can be used to save the scan results to a file instead of be
 ```bash
 osv-scanner -L package-lock.json --output scan-results.txt
 ```
+
+## C/C++ scanning
+
+OSV-Scanner supports C/C++ projects. 
+
+Because the C/C++ ecosystem does not have a centralized package manager, C/C++ dependencies tend to be bundled with the project's source code. Dependencies are either [submoduled](#submoduled-dependencies) or [vendored](#vendored-dependencies). In either case, OSV-Scanner is able to find known vulnerabilities in your project dependencies. 
+
+OSV-Scanner's C/C++ support is based on commit-level data. OSV's commit-level data covers the majority of C/C++ vulnerabilities within the OSV database, but users should be aware that there may be vulnerabilities in their dependencies that may not be in the OSV database and therefore not included in OSV-Scanner results. Adding more commit-level data to the database is an ongoing project, follow [#783](https://github.com/google/osv.dev/issues/783) for more details. 
+
+### Submoduled dependencies
+
+[Submoduled](https://git-scm.com/book/en/v2/Git-Tools-Submodules) dependencies are included in the project's source code and retain their Git histories. To scan a C/C++ project with submoduled dependencies:
+
+1. Navigate to the root folder of your project. 
+2. Ensure that your submodules are up to date using `git submodule update`. 
+3. Run scanner using `osv-scanner -r .`. 
+
+### Vendored dependencies
+
+Vendored dependencies have been directly copied into the project folder, but do not retain their Git histories. OSV-Scanner uses OSV's [determineversion API](https://google.github.io/osv.dev/post-v1-determineversion/) to estimate each dependency's version (and associated Git commit). Vulnerabilities for the estimated version are returned. This process requires no additional work from the user. Run OSV-Scanner as you normally would. 
diff --git a/internal/output/sarif.go b/internal/output/sarif.go
index e1c7c28..09a12f1 100644
--- a/internal/output/sarif.go
+++ b/internal/output/sarif.go
@@ -8,6 +8,7 @@ import (
 	"strings"
 	"text/template"
 
+	"github.com/google/osv-scanner/internal/url"
 	"github.com/google/osv-scanner/internal/utility/results"
 	"github.com/google/osv-scanner/internal/version"
 	"github.com/google/osv-scanner/pkg/models"
@@ -284,8 +285,11 @@ func PrintSARIFReport(vulnResult *models.VulnerabilityResults, outputWriter io.W
 		for pws := range gv.PkgSource {
 			artifactPath := stripGitHubWorkspace(pws.Source.Path)
 			if filepath.IsAbs(artifactPath) {
-				// Support absolute paths.
-				artifactPath = "file://" + artifactPath
+				// this only errors if the file path is not absolute,
+				// which we've already confirmed is not the case
+				p, _ := url.FromFilePath(artifactPath)
+
+				artifactPath = p.String()
 			}
 
 			run.AddDistinctArtifact(artifactPath)
diff --git a/internal/sourceanalysis/go.go b/internal/sourceanalysis/go.go
index 0258c56..4c8d119 100644
--- a/internal/sourceanalysis/go.go
+++ b/internal/sourceanalysis/go.go
@@ -10,6 +10,7 @@ import (
 	"path/filepath"
 
 	"github.com/google/osv-scanner/internal/sourceanalysis/govulncheck"
+	"github.com/google/osv-scanner/internal/url"
 	"github.com/google/osv-scanner/pkg/models"
 	"github.com/google/osv-scanner/pkg/reporter"
 	"golang.org/x/vuln/scan"
@@ -109,9 +110,13 @@ func runGovulncheck(moddir string, vulns []models.Vulnerability) (map[string][]*
 		}
 	}
 
+	// this only errors if the file path is not absolute,
+	// which paths from os.MkdirTemp should always be
+	dbdirURL, _ := url.FromFilePath(dbdir)
+
 	// Run govulncheck on the module at moddir and vulnerability database that
 	// was just created.
-	cmd := scan.Command(context.Background(), "-db", fmt.Sprintf("file://%s", dbdir), "-C", moddir, "-json", "./...")
+	cmd := scan.Command(context.Background(), "-db", dbdirURL.String(), "-C", moddir, "-json", "./...")
 	var b bytes.Buffer
 	cmd.Stdout = &b
 	if err := cmd.Start(); err != nil {
diff --git a/internal/url/url.go b/internal/url/url.go
new file mode 100644
index 0000000..08f73d3
--- /dev/null
+++ b/internal/url/url.go
@@ -0,0 +1,70 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package url
+
+import (
+	"errors"
+	"net/url"
+	"path/filepath"
+	"strings"
+)
+
+// Code copied from https://github.com/golang/go/blob/7c2b69080a0b9e35174cc9c93497b6e7176f8275/src/cmd/go/internal/web/url.go
+// TODO(golang.org/issue/32456): If accepted, move these functions into the
+// net/url package.
+
+var errNotAbsolute = errors.New("path is not absolute")
+
+func FromFilePath(path string) (*url.URL, error) {
+	if !filepath.IsAbs(path) {
+		return nil, errNotAbsolute
+	}
+
+	// If path has a Windows volume name, convert the volume to a host and prefix
+	// per https://blogs.msdn.microsoft.com/ie/2006/12/06/file-uris-in-windows/.
+	if vol := filepath.VolumeName(path); vol != "" {
+		if strings.HasPrefix(vol, `\\`) {
+			path = filepath.ToSlash(path[2:])
+			i := strings.IndexByte(path, '/')
+
+			if i < 0 {
+				// A degenerate case.
+				// \\host.example.com (without a share name)
+				// becomes
+				// file://host.example.com/
+				return &url.URL{
+					Scheme: "file",
+					Host:   path,
+					Path:   "/",
+				}, nil
+			}
+
+			// \\host.example.com\Share\path\to\file
+			// becomes
+			// file://host.example.com/Share/path/to/file
+			return &url.URL{
+				Scheme: "file",
+				Host:   path[:i],
+				Path:   filepath.ToSlash(path[i:]),
+			}, nil
+		}
+
+		// C:\path\to\file
+		// becomes
+		// file:///C:/path/to/file
+		return &url.URL{
+			Scheme: "file",
+			Path:   "/" + filepath.ToSlash(path),
+		}, nil
+	}
+
+	// /path/to/file
+	// becomes
+	// file:///path/to/file
+	return &url.URL{
+		Scheme: "file",
+		Path:   filepath.ToSlash(path),
+	}, nil
+}
diff --git a/pkg/lockfile/apk-installed.go b/pkg/lockfile/apk-installed.go
index 92a7ae6..413eba7 100644
--- a/pkg/lockfile/apk-installed.go
+++ b/pkg/lockfile/apk-installed.go
@@ -3,7 +3,6 @@ package lockfile
 import (
 	"bufio"
 	"fmt"
-	"os"
 	"sort"
 	"strings"
 )
@@ -34,7 +33,7 @@ func groupApkPackageLines(scanner *bufio.Scanner) [][]string {
 	return groups
 }
 
-func parseApkPackageGroup(group []string, pathToLockfile string) PackageDetails {
+func parseApkPackageGroup(group []string) PackageDetails {
 	var pkg = PackageDetails{
 		Ecosystem: AlpineEcosystem,
 		CompareAs: AlpineEcosystem,
@@ -52,20 +51,6 @@ func parseApkPackageGroup(group []string, pathToLockfile string) PackageDetails
 		}
 	}
 
-	if pkg.Version == "" {
-		pkgPrintName := pkg.Name
-		if pkgPrintName == "" {
-			pkgPrintName = unknownPkgName
-		}
-
-		_, _ = fmt.Fprintf(
-			os.Stderr,
-			"warning: malformed APK installed file. Found no version number in record. Package %s. File: %s\n",
-			pkgPrintName,
-			pathToLockfile,
-		)
-	}
-
 	return pkg
 }
 
@@ -87,15 +72,9 @@ func (e ApkInstalledExtractor) Extract(f DepFile) ([]PackageDetails, error) {
 	packages := make([]PackageDetails, 0, len(packageGroups))
 
 	for _, group := range packageGroups {
-		pkg := parseApkPackageGroup(group, f.Path())
+		pkg := parseApkPackageGroup(group)
 
 		if pkg.Name == "" {
-			_, _ = fmt.Fprintf(
-				os.Stderr,
-				"warning: malformed APK installed file. Found no package name in record. File: %s\n",
-				f.Path(),
-			)
-
 			continue
 		}
 
diff --git a/pkg/lockfile/dpkg-status.go b/pkg/lockfile/dpkg-status.go
index 6afadd2..404ee1b 100644
--- a/pkg/lockfile/dpkg-status.go
+++ b/pkg/lockfile/dpkg-status.go
@@ -3,7 +3,6 @@ package lockfile
 import (
 	"bufio"
 	"fmt"
-	"os"
 	"sort"
 	"strings"
 
@@ -48,7 +47,7 @@ func parseSourceField(source string) (string, string) {
 	return strings.TrimSpace(source), ""
 }
 
-func parseDpkgPackageGroup(group []string, pathToLockfile string) PackageDetails {
+func parseDpkgPackageGroup(group []string) PackageDetails {
 	var pkg = PackageDetails{
 		Ecosystem: DebianEcosystem,
 		CompareAs: DebianEcosystem,
@@ -62,14 +61,8 @@ func parseDpkgPackageGroup(group []string, pathToLockfile string) PackageDetails
 		case strings.HasPrefix(line, "Status:"):
 			status := strings.TrimPrefix(line, "Status:")
 			tokens := strings.Fields(status)
-			// Staus field is malformed. Expected: "Status: Want Flag Status"
+			// Status field is malformed. Expected: "Status: Want Flag Status"
 			if len(tokens) != 3 {
-				_, _ = fmt.Fprintf(
-					os.Stderr,
-					"warning: malformed DPKG status file. Found no valid \"Source\" field. File: %s\n",
-					pathToLockfile,
-				)
-
 				return PackageDetails{}
 			}
 			// Status field has correct number of fields but package is not installed or has only config files left
@@ -105,20 +98,6 @@ func parseDpkgPackageGroup(group []string, pathToLockfile string) PackageDetails
 		}
 	}
 
-	if pkg.Version == "" {
-		pkgPrintName := pkg.Name
-		if pkgPrintName == "" {
-			pkgPrintName = unknownPkgName
-		}
-
-		_, _ = fmt.Fprintf(
-			os.Stderr,
-			"warning: malformed DPKG status file. Found no version number in record. Package %s. File: %s\n",
-			pkgPrintName,
-			pathToLockfile,
-		)
-	}
-
 	return pkg
 }
 
@@ -139,7 +118,7 @@ func (e DpkgStatusExtractor) Extract(f DepFile) ([]PackageDetails, error) {
 	packages := make([]PackageDetails, 0, len(packageGroups))
 
 	for _, group := range packageGroups {
-		pkg := parseDpkgPackageGroup(group, f.Path())
+		pkg := parseDpkgPackageGroup(group)
 
 		// PackageDetails does not contain any field that represent a "not installed" state
 		// To manage this state and avoid false positives, empty struct means "not installed" so skip it
@@ -148,12 +127,6 @@ func (e DpkgStatusExtractor) Extract(f DepFile) ([]PackageDetails, error) {
 		}
 
 		if pkg.Name == "" {
-			_, _ = fmt.Fprintf(
-				os.Stderr,
-				"warning: malformed DPKG status file. Found no package name in record. File: %s\n",
-				f.Path(),
-			)
-
 			continue
 		}
 
diff --git a/pkg/lockfile/parse-gradle-lock.go b/pkg/lockfile/parse-gradle-lock.go
index 2bfa13f..5413768 100644
--- a/pkg/lockfile/parse-gradle-lock.go
+++ b/pkg/lockfile/parse-gradle-lock.go
@@ -3,7 +3,6 @@ package lockfile
 import (
 	"bufio"
 	"fmt"
-	"os"
 	"path/filepath"
 	"strings"
 )
@@ -63,7 +62,6 @@ func (e GradleLockExtractor) Extract(f DepFile) ([]PackageDetails, error) {
 
 		pkg, err := parseToGradlePackageDetail(lockLine)
 		if err != nil {
-			fmt.Fprintf(os.Stderr, "failed to extract from lockline: %s\n", err.Error())
 			continue
 		}
 
diff --git a/pkg/lockfile/parse.go b/pkg/lockfile/parse.go
index b10a72f..9e1a80a 100644
--- a/pkg/lockfile/parse.go
+++ b/pkg/lockfile/parse.go
@@ -8,11 +8,6 @@ import (
 	"strings"
 )
 
-// Represents when a package name could not be determined while parsing.
-// Currently, parsers are expected to omit such packages from their results.
-// Using a const is required to avoid linter error (goconst) due to multiple usage in parsers.
-const unknownPkgName = "<unknown>"
-
 func FindParser(pathToLockfile string, parseAs string) (PackageDetailsParser, string) {
 	if parseAs == "" {
 		parseAs = filepath.Base(pathToLockfile)
diff --git a/pkg/osvscanner/osvscanner.go b/pkg/osvscanner/osvscanner.go
index bc334e7..38ed2f7 100644
--- a/pkg/osvscanner/osvscanner.go
+++ b/pkg/osvscanner/osvscanner.go
@@ -247,6 +247,10 @@ func queryDetermineVersions(repoDir string) (*osv.DetermineVersionResponse, erro
 				// results with our regular git commit scanning.
 				return filepath.SkipDir
 			}
+			if _, ok := vendoredLibNames[strings.ToLower(info.Name())]; ok {
+				// Ignore nested vendored libraries, as they can cause bad matches.
+				return filepath.SkipDir
+			}
 
 			return nil
 		}


Test patch:
diff --git a/cmd/osv-scanner/main_test.go b/cmd/osv-scanner/main_test.go
index ff124d8..20efc57 100644
--- a/cmd/osv-scanner/main_test.go
+++ b/cmd/osv-scanner/main_test.go
@@ -787,7 +787,8 @@ func TestRun_GithubActions(t *testing.T) {
                         "markdown": "An issue in Archive v3.3.7 allows attackers to spoof zip filenames which can lead to inconsistent filename parsing."
                       },
                       "deprecatedIds": [
-                        "CVE-2023-39137"
+                        "CVE-2023-39137",
+                        "GHSA-r285-q736-9v95"
                       ],
                       "help": {
                         "text": "%%",
@@ -805,7 +806,8 @@ func TestRun_GithubActions(t *testing.T) {
                         "markdown": "An issue in Archive v3.3.7 allows attackers to execute a path traversal via extracting a crafted zip file."
                       },
                       "deprecatedIds": [
-                        "CVE-2023-39139"
+                        "CVE-2023-39139",
+                        "GHSA-9v85-q87q-g4vg"
                       ],
                       "help": {
                         "text": "%%",
@@ -830,7 +832,7 @@ func TestRun_GithubActions(t *testing.T) {
                   "ruleIndex": 0,
                   "level": "warning",
                   "message": {
-                    "text": "Package 'https://github.com/brendan-duncan/archive.git@9de7a054' is vulnerable to 'CVE-2023-39137'."
+                    "text": "Package 'https://github.com/brendan-duncan/archive.git@9de7a054' is vulnerable to 'CVE-2023-39137' (also known as 'GHSA-r285-q736-9v95')."
                   },
                   "locations": [
                     {
@@ -847,7 +849,7 @@ func TestRun_GithubActions(t *testing.T) {
                   "ruleIndex": 1,
                   "level": "warning",
                   "message": {
-                    "text": "Package 'https://github.com/brendan-duncan/archive.git@9de7a054' is vulnerable to 'CVE-2023-39139'."
+                    "text": "Package 'https://github.com/brendan-duncan/archive.git@9de7a054' is vulnerable to 'CVE-2023-39139' (also known as 'GHSA-9v85-q87q-g4vg')."
                   },
                   "locations": [
                     {
diff --git a/internal/url/url_other_test.go b/internal/url/url_other_test.go
new file mode 100644
index 0000000..392cf5d
--- /dev/null
+++ b/internal/url/url_other_test.go
@@ -0,0 +1,38 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !windows
+
+package url
+
+// Code copied from https://github.com/golang/go/blob/7c2b69080a0b9e35174cc9c93497b6e7176f8275/src/cmd/go/internal/web/url_other_test.go
+
+var urlTests = []struct {
+	url          string
+	filePath     string
+	canonicalURL string // If empty, assume equal to url.
+	wantErr      string
+}{
+	// Examples from RFC 8089:
+	{
+		url:      `file:///path/to/file`,
+		filePath: `/path/to/file`,
+	},
+	{
+		url:          `file:/path/to/file`,
+		filePath:     `/path/to/file`,
+		canonicalURL: `file:///path/to/file`,
+	},
+	{
+		url:          `file://localhost/path/to/file`,
+		filePath:     `/path/to/file`,
+		canonicalURL: `file:///path/to/file`,
+	},
+
+	// We reject non-local files.
+	{
+		url:     `file://host.example.com/path/to/file`,
+		wantErr: "file URL specifies non-local host",
+	},
+}
diff --git a/internal/url/url_test.go b/internal/url/url_test.go
new file mode 100644
index 0000000..595786a
--- /dev/null
+++ b/internal/url/url_test.go
@@ -0,0 +1,50 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package url
+
+import (
+	"testing"
+)
+
+// Code copied from https://github.com/golang/go/blob/7c2b69080a0b9e35174cc9c93497b6e7176f8275/src/cmd/go/internal/web/url_test.go
+
+func TestURLFromFilePath(t *testing.T) {
+	t.Parallel()
+
+	for _, tc := range urlTests {
+		if tc.filePath == "" {
+			continue
+		}
+		tc := tc
+
+		t.Run(tc.filePath, func(t *testing.T) {
+			t.Parallel()
+
+			u, err := FromFilePath(tc.filePath)
+			if err != nil {
+				if err.Error() == tc.wantErr {
+					return
+				}
+				if tc.wantErr == "" {
+					t.Fatalf("urlFromFilePath(%v): %v; want <nil>", tc.filePath, err)
+				} else {
+					t.Fatalf("urlFromFilePath(%v): %v; want %s", tc.filePath, err, tc.wantErr)
+				}
+			}
+
+			if tc.wantErr != "" {
+				t.Fatalf("urlFromFilePath(%v) = <nil>; want error: %s", tc.filePath, tc.wantErr)
+			}
+
+			wantURL := tc.url
+			if tc.canonicalURL != "" {
+				wantURL = tc.canonicalURL
+			}
+			if u.String() != wantURL {
+				t.Errorf("urlFromFilePath(%v) = %v; want %s", tc.filePath, u, wantURL)
+			}
+		})
+	}
+}
diff --git a/internal/url/url_windows_test.go b/internal/url/url_windows_test.go
new file mode 100644
index 0000000..1cf7e5a
--- /dev/null
+++ b/internal/url/url_windows_test.go
@@ -0,0 +1,96 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package url
+
+// Code copied from https://github.com/golang/go/blob/7c2b69080a0b9e35174cc9c93497b6e7176f8275/src/cmd/go/internal/web/url_windows_test.go
+
+var urlTests = []struct {
+	url          string
+	filePath     string
+	canonicalURL string // If empty, assume equal to url.
+	wantErr      string
+}{
+	// Examples from https://blogs.msdn.microsoft.com/ie/2006/12/06/file-uris-in-windows/:
+
+	{
+		url:      `file://laptop/My%20Documents/FileSchemeURIs.doc`,
+		filePath: `\\laptop\My Documents\FileSchemeURIs.doc`,
+	},
+	{
+		url:      `file:///C:/Documents%20and%20Settings/davris/FileSchemeURIs.doc`,
+		filePath: `C:\Documents and Settings\davris\FileSchemeURIs.doc`,
+	},
+	{
+		url:      `file:///D:/Program%20Files/Viewer/startup.htm`,
+		filePath: `D:\Program Files\Viewer\startup.htm`,
+	},
+	{
+		url:          `file:///C:/Program%20Files/Music/Web%20Sys/main.html?REQUEST=RADIO`,
+		filePath:     `C:\Program Files\Music\Web Sys\main.html`,
+		canonicalURL: `file:///C:/Program%20Files/Music/Web%20Sys/main.html`,
+	},
+	{
+		url:      `file://applib/products/a-b/abc_9/4148.920a/media/start.swf`,
+		filePath: `\\applib\products\a-b\abc_9\4148.920a\media\start.swf`,
+	},
+	{
+		url:     `file:////applib/products/a%2Db/abc%5F9/4148.920a/media/start.swf`,
+		wantErr: "file URL missing drive letter",
+	},
+	{
+		url:     `C:\Program Files\Music\Web Sys\main.html?REQUEST=RADIO`,
+		wantErr: "non-file URL",
+	},
+
+	// The example "file://D:\Program Files\Viewer\startup.htm" errors out in
+	// url.Parse, so we substitute a slash-based path for testing instead.
+	{
+		url:     `file://D:/Program Files/Viewer/startup.htm`,
+		wantErr: "file URL encodes volume in host field: too few slashes?",
+	},
+
+	// The blog post discourages the use of non-ASCII characters because they
+	// depend on the user's current codepage. However, when we are working with Go
+	// strings we assume UTF-8 encoding, and our url package refuses to encode
+	// URLs to non-ASCII strings.
+	{
+		url:          `file:///C:/exampleㄓ.txt`,
+		filePath:     `C:\exampleㄓ.txt`,
+		canonicalURL: `file:///C:/example%E3%84%93.txt`,
+	},
+	{
+		url:      `file:///C:/example%E3%84%93.txt`,
+		filePath: `C:\exampleㄓ.txt`,
+	},
+
+	// Examples from RFC 8089:
+
+	// We allow the drive-letter variation from section E.2, because it is
+	// simpler to support than not to. However, we do not generate the shorter
+	// form in the reverse direction.
+	{
+		url:          `file:c:/path/to/file`,
+		filePath:     `c:\path\to\file`,
+		canonicalURL: `file:///c:/path/to/file`,
+	},
+
+	// We encode the UNC share name as the authority following section E.3.1,
+	// because that is what the Microsoft blog post explicitly recommends.
+	{
+		url:      `file://host.example.com/Share/path/to/file.txt`,
+		filePath: `\\host.example.com\Share\path\to\file.txt`,
+	},
+
+	// We decline the four- and five-slash variations from section E.3.2.
+	// The paths in these URLs would change meaning under path.Clean.
+	{
+		url:     `file:////host.example.com/path/to/file`,
+		wantErr: "file URL missing drive letter",
+	},
+	{
+		url:     `file://///host.example.com/path/to/file`,
+		wantErr: "file URL missing drive letter",
+	},
+}