Repository: google/osv-scanner

Issue:
Offline scan for custom lockfile (C/C++ project from git project) skipped
Hello, osv-scanner have awesome functionalities 
- Scan custom lockfile: to scan  C/C++ dependencies from github projects
- A downloadable copy of the OSV database (stored in a GCS bucket maintained by OSV)

But i seems, it is not possible to scan custom lockfile using offline mirror of OSV database...

## reproduce

- my commands to mirror the database:

```
❯ export OSV_SCANNER_LOCAL_DB_CACHE_DIRECTORY="$HOME/.cache"
❯ for eco in $(gsutil cat gs://osv-vulnerabilities/ecosystems.txt); do
    mkdir -p "$OSV_SCANNER_LOCAL_DB_CACHE_DIRECTORY/osv-scanner/$eco"
    gsutil cp gs://osv-vulnerabilities/$eco/all.zip "$OSV_SCANNER_LOCAL_DB_CACHE_DIRECTORY/osv-scanner/$eco/"
done

Copying gs://osv-vulnerabilities/AlmaLinux/all.zip...
- [1 files][  3.7 MiB/  3.7 MiB]                                                
Operation completed over 1 objects/3.7 MiB.                                      
Copying gs://osv-vulnerabilities/Alpine/all.zip...
- [1 files][ 11.8 MiB/ 11.8 MiB]                                                
Operation completed over 1 objects/11.8 MiB.                                     
Copying gs://osv-vulnerabilities/Android/all.zip...
- [1 files][  4.8 MiB/  4.8 MiB]                                                
Operation completed over 1 objects/4.8 MiB.                                      
Copying gs://osv-vulnerabilities/Bitnami/all.zip...
- [1 files][  5.4 MiB/  5.4 MiB]                                                
Operation completed over 1 objects/5.4 MiB.                                      
Copying gs://osv-vulnerabilities/CRAN/all.zip...
/ [1 files][  9.2 KiB/  9.2 KiB]                                                
Operation completed over 1 objects/9.2 KiB.                                      
Copying gs://osv-vulnerabilities/Chainguard/all.zip...
- [1 files][ 14.5 MiB/ 14.5 MiB]                                                
Operation completed over 1 objects/14.5 MiB.                                     
Copying gs://osv-vulnerabilities/Debian/all.zip...
| [1 files][ 64.2 MiB/ 64.2 MiB]                                                
Operation completed over 1 objects/64.2 MiB.                                     
Copying gs://osv-vulnerabilities/GHC/all.zip...
/ [1 files][  2.5 KiB/  2.5 KiB]                                                
Operation completed over 1 objects/2.5 KiB.                                      
Copying gs://osv-vulnerabilities/GIT/all.zip...
\ [1 files][ 34.9 MiB/ 34.9 MiB]                                                
Operation completed over 1 objects/34.9 MiB.                                     
Copying gs://osv-vulnerabilities/GSD/all.zip...
/ [1 files][  5.5 KiB/  5.5 KiB]                                                
Operation completed over 1 objects/5.5 KiB.                                      
CommandException: No URLs matched: gs://osv-vulnerabilities/GitHub/all.zip
CommandException: No URLs matched: gs://osv-vulnerabilities/Actions/all.zip
Copying gs://osv-vulnerabilities/Go/all.zip...
- [1 files][  4.7 MiB/  4.7 MiB]                                                
Operation completed over 1 objects/4.7 MiB.                                      
Copying gs://osv-vulnerabilities/Hackage/all.zip...
/ [1 files][ 32.4 KiB/ 32.4 KiB]                                                
Operation completed over 1 objects/32.4 KiB.                                     
Copying gs://osv-vulnerabilities/Hex/all.zip...
/ [1 files][ 43.3 KiB/ 43.3 KiB]                                                
Operation completed over 1 objects/43.3 KiB.                                     
Copying gs://osv-vulnerabilities/Linux/all.zip...
\ [1 files][ 28.3 MiB/ 28.3 MiB]                                                
Operation completed over 1 objects/28.3 MiB.                                     
Copying gs://osv-vulnerabilities/Mageia/all.zip...
- [1 files][  5.7 MiB/  5.7 MiB]                                                
Operation completed over 1 objects/5.7 MiB.                                      
Copying gs://osv-vulnerabilities/Maven/all.zip...
- [1 files][  7.6 MiB/  7.6 MiB]                                                
Operation completed over 1 objects/7.6 MiB.                                      
Copying gs://osv-vulnerabilities/MinimOS/all.zip...
- [1 files][989.7 KiB/989.7 KiB]                                                
Operation completed over 1 objects/989.7 KiB.                                    
Copying gs://osv-vulnerabilities/NuGet/all.zip...
- [1 files][  1.6 MiB/  1.6 MiB]                                                
Operation completed over 1 objects/1.6 MiB.                                      
Copying gs://osv-vulnerabilities/OSS-Fuzz/all.zip...
- [1 files][  2.8 MiB/  2.8 MiB]                                                
Operation completed over 1 objects/2.8 MiB.                                      
Copying gs://osv-vulnerabilities/Packagist/all.zip...
- [1 files][  6.1 MiB/  6.1 MiB]                                                
Operation completed over 1 objects/6.1 MiB.                                      
Copying gs://osv-vulnerabilities/Pub/all.zip...
/ [1 files][ 18.3 KiB/ 18.3 KiB]                                                
Operation completed over 1 objects/18.3 KiB.                                     
Copying gs://osv-vulnerabilities/PyPI/all.zip...
- [1 files][ 17.2 MiB/ 17.2 MiB]                                                
Operation completed over 1 objects/17.2 MiB.                                     
CommandException: No URLs matched: gs://osv-vulnerabilities/Red/all.zip
CommandException: No URLs matched: gs://osv-vulnerabilities/Hat/all.zip
CommandException: No URLs matched: gs://osv-vulnerabilities/Rocky/all.zip
Copying gs://osv-vulnerabilities/Linux/all.zip...
\ [1 files][ 28.3 MiB/ 28.3 MiB]                                                
Operation completed over 1 objects/28.3 MiB.                                     
Copying gs://osv-vulnerabilities/RubyGems/all.zip...
- [1 files][  1.9 MiB/  1.9 MiB]                                                
Operation completed over 1 objects/1.9 MiB.                                      
Copying gs://osv-vulnerabilities/SUSE/all.zip...
\ [1 files][ 32.9 MiB/ 32.9 MiB]                                                
Operation completed over 1 objects/32.9 MiB.                                     
Copying gs://osv-vulnerabilities/SwiftURL/all.zip...
/ [1 files][ 62.8 KiB/ 62.8 KiB]                                                
Operation completed over 1 objects/62.8 KiB.                                     
Copying gs://osv-vulnerabilities/UVI/all.zip...
/ [1 files][  1.1 KiB/  1.1 KiB]                                                
Operation completed over 1 objects/1.1 KiB.                                      
Copying gs://osv-vulnerabilities/Ubuntu/all.zip...
| [1 files][332.5 MiB/332.5 MiB]                                                
Operation completed over 1 objects/332.5 MiB.                                    
Copying gs://osv-vulnerabilities/Wolfi/all.zip...
- [1 files][  8.1 MiB/  8.1 MiB]                                                
Operation completed over 1 objects/8.1 MiB.                                      
CommandException: Destination (/home/user/.cache/osv-scanner/[EMPTY]/) must match exactly 1 URL
Copying gs://osv-vulnerabilities/crates.io/all.zip...
- [1 files][  2.0 MiB/  2.0 MiB]                                                
Operation completed over 1 objects/2.0 MiB.                                      
Copying gs://osv-vulnerabilities/npm/all.zip...
\ [1 files][ 27.4 MiB/ 27.4 MiB]                                                
Operation completed over 1 objects/27.4 MiB.                                     
Copying gs://osv-vulnerabilities/openSUSE/all.zip...
- [1 files][ 16.0 MiB/ 16.0 MiB]                                                
Operation completed over 1 objects/16.0 MiB.
```

- an example of a custom lockfile `osv-scanner.json`:
```
{
  "results": [
    {
      "packages": [
        {
          "package": {
            "name": "github.com/openssl/openssl",
            "commit": "45fda76bc1b9fd74d10e85e0ce9b65a12dcc58b0"
          }
        }
      ]
    }
  ]
}
```

- the scan online works:

```
❯ osv-scanner --lockfile osv-scanner:osv-scanner.json --format markdown                                                       

Scanned /home/user/Documents/foo/osv-scanner.json file as a osv-scanner and found 1 package
| OSV URL | CVSS | Ecosystem | Package | Version | Source |
| --- | --- | --- | --- | --- | --- |
| https://osv.dev/CVE-2024-12797 |  | GIT | github.com/openssl/openssl@45fda76b | github.com/openssl/openssl@45fda76b | osv-scanner.json |
| https://osv.dev/CVE-2024-13176 |  | GIT | github.com/openssl/openssl@45fda76b | github.com/openssl/openssl@45fda76b | osv-scanner.json |
| https://osv.dev/CVE-2024-9143 |  | GIT | github.com/openssl/openssl@45fda76b | github.com/openssl/openssl@45fda76b | osv-scanner.json |
```

- the scan offline is skipped, even with mirrored database:
```
❯ osv-scanner --lockfile osv-scanner:osv-scanner.json --format markdown --offline

Scanned /home/user/Documents/foo/osv-scanner.json file as a osv-scanner and found 1 package
Skipping commit scanning for: 45fda76bc1b9fd74d10e85e0ce9b65a12dcc58b0
No issues found
```
```
❯ osv-scanner --lockfile osv-scanner:osv-scanner.json --format markdown --offline-vulnerabilities --download-offline-databases

Scanned /home/user/Documents/foo/osv-scanner.json file as a osv-scanner and found 1 package
Skipping commit scanning for: 45fda76bc1b9fd74d10e85e0ce9b65a12dcc58b0
No issues found
```

Can you help me to scan a custom lockfile on offline network please ?
If it is not possible, is there a way to have an offline version of `apo.osv.dev` ?


Discussion:
@another-rex: The issue is doing commit based scanning in offline mode, which is not possible right now. (https://google.github.io/osv-scanner/usage/offline-mode/#limitations). 

Because commits are unordered, we have to index **every single commit** that is vulnerable when we get a record, which as you can imagine is a lot of data and not really feasible to download and run locally. @cybops35: Ok my bad, but hope it would be possible some day :) 
Have a good day@cybops35: Hi @another-rex  ! Would it be more feasible to have Github "tag" based scanning in offline mode ? Maybe the dataset is significantly smaller ?
Or, is there a way to build our own offline tag/commit based scanning database from a subset of chosen repositories ?@another-rex: Good point, when we designed offline scanning we didn't have tag information then. tag based scanning is likely something we can do, I'll look into it. @another-rex: @G-Rath This is the url for the git ecosystem zip. https://storage.googleapis.com/osv-test-vulnerabilities/GIT/all.zip@bamiaux: We've found that in our case, the only way to scan third-party c/c++ dependencies is to use custom lockfiles. 
We map specific versions (openssl or any required c/c++ dependency) to their specific commits and use it in the lockfile. We don't really use the full power of custom lockfiles, as we only checkout tagged versions.

Having a stripped database of commits containing only tags, would help us doing scans offline.

It is our undestanding that there is no other way to specify in a project that "we depend on OpenSSL 3.2.3"

Solution patch:
diff --git a/cmd/osv-scanner/__snapshots__/main_test.snap b/cmd/osv-scanner/__snapshots__/main_test.snap
index 91f59bae..8b57b295 100755
--- a/cmd/osv-scanner/__snapshots__/main_test.snap
+++ b/cmd/osv-scanner/__snapshots__/main_test.snap
@@ -24,7 +24,7 @@ OPTIONS:
 
 [Test_run/version - 1]
 osv-scanner version: 2.2.2
-osv-scalibr version: 0.3.2
+osv-scalibr version: 0.3.4
 commit: n/a
 built at: n/a
 
diff --git a/cmd/osv-scanner/scan/source/__snapshots__/command_test.snap b/cmd/osv-scanner/scan/source/__snapshots__/command_test.snap
index af07cf88..eecb7c41 100755
--- a/cmd/osv-scanner/scan/source/__snapshots__/command_test.snap
+++ b/cmd/osv-scanner/scan/source/__snapshots__/command_test.snap
@@ -1697,6 +1697,59 @@ Total 0 packages affected by 0 known vulnerabilities (0 Critical, 0 High, 0 Medi
 
 ---
 
+[TestCommand_CommitSupport/offline_uses_git_tags - 1]
+Scanned <rootdir>/testdata/locks-git/osv-scanner.json file as a osv-scanner and found 4 packages
+Skipping commit scanning for: 45fda76bc1b9fd74d10e85e0ce9b65a12dcc58b0
+Loaded GIT local db from <tempdir>/osv-scanner/GIT/all.zip
+Total 2 packages affected by 6 known vulnerabilities (2 Critical, 2 High, 0 Medium, 0 Low, 2 Unknown) from 1 ecosystem.
+0 vulnerabilities can be fixed.
+
+
++--------------------------------+------+-----------+--------------------------+--------------------------+---------------+-------------------------------------+
+| OSV URL                        | CVSS | ECOSYSTEM | PACKAGE                  | VERSION                  | FIXED VERSION | SOURCE                              |
++--------------------------------+------+-----------+--------------------------+--------------------------+---------------+-------------------------------------+
+| https://osv.dev/CVE-2016-2183  | 7.5  | GIT       |     https://github.com/openssl/openssl@aea7aaf2     | --            | testdata/locks-git/osv-scanner.json |
+| https://osv.dev/CVE-2025-4575  |      | GIT       |     https://github.com/openssl/openssl@aea7aaf2     | --            | testdata/locks-git/osv-scanner.json |
+| https://osv.dev/CVE-2016-10931 | 8.1  | GIT       |  https://github.com/sfackler/rust-openssl@0f428d19  | --            | testdata/locks-git/osv-scanner.json |
+| https://osv.dev/CVE-2018-20997 | 9.8  | GIT       |  https://github.com/sfackler/rust-openssl@0f428d19  | --            | testdata/locks-git/osv-scanner.json |
+| https://osv.dev/CVE-2023-53159 | 9.1  | GIT       |  https://github.com/sfackler/rust-openssl@0f428d19  | --            | testdata/locks-git/osv-scanner.json |
+| https://osv.dev/CVE-2025-3416  |      | GIT       |  https://github.com/sfackler/rust-openssl@0f428d19  | --            | testdata/locks-git/osv-scanner.json |
++--------------------------------+------+-----------+-----------------------------------------------------+---------------+-------------------------------------+
+
+---
+
+[TestCommand_CommitSupport/offline_uses_git_tags - 2]
+
+---
+
+[TestCommand_CommitSupport/online_uses_git_commits - 1]
+Scanned <rootdir>/testdata/locks-git/osv-scanner.json file as a osv-scanner and found 4 packages
+Total 3 packages affected by 11 known vulnerabilities (3 Critical, 1 High, 2 Medium, 0 Low, 5 Unknown) from 1 ecosystem.
+0 vulnerabilities can be fixed.
+
+
++--------------------------------+------+-----------+----------------------------+-----------------------------+---------------+-------------------------------------+
+| OSV URL                        | CVSS | ECOSYSTEM | PACKAGE                    | VERSION                     | FIXED VERSION | SOURCE                              |
++--------------------------------+------+-----------+----------------------------+-----------------------------+---------------+-------------------------------------+
+| https://osv.dev/CVE-2024-12797 |      | GIT       |        https://github.com/openssl/openssl@45fda76b       | --            | testdata/locks-git/osv-scanner.json |
+| https://osv.dev/CVE-2024-13176 |      | GIT       |        https://github.com/openssl/openssl@45fda76b       | --            | testdata/locks-git/osv-scanner.json |
+| https://osv.dev/CVE-2024-9143  |      | GIT       |        https://github.com/openssl/openssl@45fda76b       | --            | testdata/locks-git/osv-scanner.json |
+| https://osv.dev/CVE-2023-53159 | 9.1  | GIT       |  https://github.com/sfackler-fork/rust-openssl@3b064fdb  | --            | testdata/locks-git/osv-scanner.json |
+| https://osv.dev/CVE-2023-6180  | 5.3  | GIT       |  https://github.com/sfackler-fork/rust-openssl@3b064fdb  | --            | testdata/locks-git/osv-scanner.json |
+| https://osv.dev/CVE-2025-3416  |      | GIT       |  https://github.com/sfackler-fork/rust-openssl@3b064fdb  | --            | testdata/locks-git/osv-scanner.json |
+| https://osv.dev/CVE-2016-10931 | 8.1  | GIT       |     https://github.com/sfackler/rust-openssl@0f428d19    | --            | testdata/locks-git/osv-scanner.json |
+| https://osv.dev/CVE-2018-20997 | 9.8  | GIT       |     https://github.com/sfackler/rust-openssl@0f428d19    | --            | testdata/locks-git/osv-scanner.json |
+| https://osv.dev/CVE-2023-53159 | 9.1  | GIT       |     https://github.com/sfackler/rust-openssl@0f428d19    | --            | testdata/locks-git/osv-scanner.json |
+| https://osv.dev/CVE-2023-6180  | 5.3  | GIT       |     https://github.com/sfackler/rust-openssl@0f428d19    | --            | testdata/locks-git/osv-scanner.json |
+| https://osv.dev/CVE-2025-3416  |      | GIT       |     https://github.com/sfackler/rust-openssl@0f428d19    | --            | testdata/locks-git/osv-scanner.json |
++--------------------------------+------+-----------+----------------------------------------------------------+---------------+-------------------------------------+
+
+---
+
+[TestCommand_CommitSupport/online_uses_git_commits - 2]
+
+---
+
 [TestCommand_ExplicitExtractors_WithDefaults/empty_plugins_flag_does_nothing - 1]
 
 ---
@@ -4299,6 +4352,74 @@ Total 3 packages affected by 8 known vulnerabilities (0 Critical, 3 High, 4 Medi
 ---
 
 [TestCommand_Transitive/resolves_transitive_dependencies_with_native_data_source - 1]
+Fetching response from: https://dl.google.com/dl/android/maven2/org/apache/logging/log4j/log4j-web/2.14.1/log4j-web-2.14.1.pom
+Fetching response from: https://repo.maven.apache.org/maven2/org/apache/logging/log4j/log4j-web/2.14.1/log4j-web-2.14.1.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services/10.0.0/play-services-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/org/apache/logging/log4j/log4j/2.14.1/log4j-2.14.1.pom
+Fetching response from: https://repo.maven.apache.org/maven2/org/apache/logging/log4j/log4j/2.14.1/log4j-2.14.1.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/org/apache/logging/logging-parent/3/logging-parent-3.pom
+Fetching response from: https://repo.maven.apache.org/maven2/org/apache/logging/logging-parent/3/logging-parent-3.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/org/apache/apache/23/apache-23.pom
+Fetching response from: https://repo.maven.apache.org/maven2/org/apache/apache/23/apache-23.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/org/apache/logging/log4j/log4j-api/2.14.1/log4j-api-2.14.1.pom
+Fetching response from: https://repo.maven.apache.org/maven2/org/apache/logging/log4j/log4j-api/2.14.1/log4j-api-2.14.1.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/org/apache/logging/log4j/log4j-core/2.14.1/log4j-core-2.14.1.pom
+Fetching response from: https://repo.maven.apache.org/maven2/org/apache/logging/log4j/log4j-core/2.14.1/log4j-core-2.14.1.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-ads/10.0.0/play-services-ads-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-ads-lite/10.0.0/play-services-ads-lite-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-analytics/10.0.0/play-services-analytics-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-analytics-impl/10.0.0/play-services-analytics-impl-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-appinvite/10.0.0/play-services-appinvite-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-auth/10.0.0/play-services-auth-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-auth-base/10.0.0/play-services-auth-base-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-base/10.0.0/play-services-base-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-cast-framework/10.0.0/play-services-cast-framework-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-cast/10.0.0/play-services-cast-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-clearcut/10.0.0/play-services-clearcut-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-basement/10.0.0/play-services-basement-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/firebase/firebase-config/10.0.0/firebase-config-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-awareness/10.0.0/play-services-awareness-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/firebase/firebase-crash/10.0.0/firebase-crash-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-drive/10.0.0/play-services-drive-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/firebase/firebase-auth/10.0.0/firebase-auth-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/firebase/firebase-database-connection/10.0.0/firebase-database-connection-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/firebase/firebase-database/10.0.0/firebase-database-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/firebase/firebase-iid/10.0.0/firebase-iid-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/firebase/firebase-messaging/10.0.0/firebase-messaging-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/firebase/firebase-storage/10.0.0/firebase-storage-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/firebase/firebase-storage-common/10.0.0/firebase-storage-common-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/firebase/firebase-common/10.0.0/firebase-common-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-fitness/10.0.0/play-services-fitness-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-games/10.0.0/play-services-games-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-gass/10.0.0/play-services-gass-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-gcm/10.0.0/play-services-gcm-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/firebase/firebase-appindexing/10.0.0/firebase-appindexing-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-identity/10.0.0/play-services-identity-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-iid/10.0.0/play-services-iid-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-instantapps/10.0.0/play-services-instantapps-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-location/10.0.0/play-services-location-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-maps/10.0.0/play-services-maps-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/firebase/firebase-analytics/10.0.0/firebase-analytics-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/firebase/firebase-analytics-impl/10.0.0/firebase-analytics-impl-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-nearby/10.0.0/play-services-nearby-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-panorama/10.0.0/play-services-panorama-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-places/10.0.0/play-services-places-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-plus/10.0.0/play-services-plus-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-safetynet/10.0.0/play-services-safetynet-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-tagmanager-api/10.0.0/play-services-tagmanager-api-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-tagmanager/10.0.0/play-services-tagmanager-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-tagmanager-v4-impl/10.0.0/play-services-tagmanager-v4-impl-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-tasks/10.0.0/play-services-tasks-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-vision/10.0.0/play-services-vision-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-wallet/10.0.0/play-services-wallet-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-wearable/10.0.0/play-services-wearable-10.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/android/support/mediarouter-v7/24.0.0/mediarouter-v7-24.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/android/support/support-v4/24.0.0/support-v4-24.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/android/support/palette-v7/24.0.0/palette-v7-24.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/android/support/appcompat-v7/24.0.0/appcompat-v7-24.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/android/support/support-annotations/24.0.0/support-annotations-24.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/android/support/support-vector-drawable/24.0.0/support-vector-drawable-24.0.0.pom
+Fetching response from: https://dl.google.com/dl/android/maven2/com/android/support/animated-vector-drawable/24.0.0/animated-vector-drawable-24.0.0.pom
 Scanned <rootdir>/testdata/maven-transitive/registry.xml file as a pom.xml and found 59 packages
 Total 2 packages affected by 5 known vulnerabilities (2 Critical, 1 High, 2 Medium, 0 Low, 0 Unknown) from 1 ecosystem.
 5 vulnerabilities can be fixed.
diff --git a/go.mod b/go.mod
index 95744393..7705a97e 100644
--- a/go.mod
+++ b/go.mod
@@ -16,12 +16,12 @@ require (
 	github.com/gkampitakis/go-snaps v0.5.15
 	github.com/go-git/go-git/v5 v5.16.2
 	github.com/google/go-cmp v0.7.0
-	github.com/google/osv-scalibr v0.3.3-0.20250829011816-004b493f3b78
+	github.com/google/osv-scalibr v0.3.4
 	github.com/ianlancetaylor/demangle v0.0.0-20250628045327-2d64ad6b7ec5
 	github.com/jedib0t/go-pretty/v6 v6.6.8
 	github.com/muesli/reflow v0.3.0
 	github.com/opencontainers/go-digest v1.0.0
-	github.com/ossf/osv-schema/bindings/go v0.0.0-20250922001250-9fc1e2b3ee88
+	github.com/ossf/osv-schema/bindings/go v0.0.0-20250926044009-f6ae0b6bae32
 	github.com/owenrumney/go-sarif/v3 v3.2.3
 	github.com/package-url/packageurl-go v0.1.3
 	github.com/pandatix/go-cvss v0.6.2
@@ -37,13 +37,14 @@ require (
 	google.golang.org/protobuf v1.36.9
 	gopkg.in/ini.v1 v1.67.0
 	gopkg.in/yaml.v3 v3.0.1
-	osv.dev/bindings/go v0.0.0-20250922045631-2718b40f69af
+	osv.dev/bindings/go v0.0.0-20250929041518-3b73304a1688
 )
 
 require (
+	cloud.google.com/go/compute/metadata v0.8.4 // indirect
 	dario.cat/mergo v1.0.2 // indirect
-	deps.dev/api/v3alpha v0.0.0-20250630145910-0bba51f925b0 // indirect
-	deps.dev/util/pypi v0.0.0-20250630145910-0bba51f925b0 // indirect
+	deps.dev/api/v3alpha v0.0.0-20250903005441-604c45d5b44b // indirect
+	deps.dev/util/pypi v0.0.0-20250903005441-604c45d5b44b // indirect
 	github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect
 	github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20250520111509-a70c2aa677fa // indirect
 	github.com/GehirnInc/crypt v0.0.0-20230320061759-8cc1b52080c5 // indirect
@@ -152,6 +153,7 @@ require (
 	github.com/spdx/tools-golang v0.5.5 // indirect
 	github.com/tidwall/jsonc v0.3.2 // indirect
 	github.com/tidwall/match v1.1.1 // indirect
+	github.com/tink-crypto/tink-go/v2 v2.4.0 // indirect
 	github.com/tklauser/go-sysconf v0.3.15 // indirect
 	github.com/tklauser/numcpus v0.10.0 // indirect
 	github.com/tonistiigi/go-csvvalue v0.0.0-20240814133006-030d3b2625d0 // indirect
@@ -176,6 +178,7 @@ require (
 	golang.org/x/crypto v0.42.0 // indirect
 	golang.org/x/exp v0.0.0-20250711185948-6ae5c78190dc // indirect
 	golang.org/x/mod v0.27.0 // indirect
+	golang.org/x/oauth2 v0.30.0 // indirect
 	golang.org/x/sys v0.36.0 // indirect
 	golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488 // indirect
 	golang.org/x/text v0.29.0 // indirect
diff --git a/go.sum b/go.sum
index 55df442b..deee33e5 100644
--- a/go.sum
+++ b/go.sum
@@ -1,14 +1,16 @@
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go/compute/metadata v0.8.4 h1:oXMa1VMQBVCyewMIOm3WQsnVd9FbKBtm8reqWRaXnHQ=
+cloud.google.com/go/compute/metadata v0.8.4/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=
 dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
 dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
 deps.dev/api/v3 v3.0.0-20250917073939-6ff3dd7d2eea h1:kyKkITzeRX659i4FwCAJrqreUxKap7jbR9CS8ViwBeA=
 deps.dev/api/v3 v3.0.0-20250917073939-6ff3dd7d2eea/go.mod h1:MntdDuD/RI8T19XT1AG/4ymbtIbjWJDQdqc+oT0Wmp4=
-deps.dev/api/v3alpha v0.0.0-20250630145910-0bba51f925b0 h1:wrI8rh7j+MExb5TUhZiUbPVXPqsT6z9+Dj0k39zFB5o=
-deps.dev/api/v3alpha v0.0.0-20250630145910-0bba51f925b0/go.mod h1:n8TeIsqiv9yuAQwdHfd85jfDp8Ed0Xka5iysKkQ7Zxw=
+deps.dev/api/v3alpha v0.0.0-20250903005441-604c45d5b44b h1:iXre7CzhkmdmzAdiOi+u/Yk1iDMI9SYlFEnXgJd5Rnk=
+deps.dev/api/v3alpha v0.0.0-20250903005441-604c45d5b44b/go.mod h1:CJqVceLEA55Tu9QwNoaUX4HhvzRQnYjCL1jUdw/rhPQ=
 deps.dev/util/maven v0.0.0-20250917073939-6ff3dd7d2eea h1:z7rc677/VSowKnxEBvj1S4XXihsB7VbHP2+Gw0vuSCM=
 deps.dev/util/maven v0.0.0-20250917073939-6ff3dd7d2eea/go.mod h1:eGrXziwI7scSGrwIj+5EBHtTeSxAZD/yi8Hb3nFXesA=
-deps.dev/util/pypi v0.0.0-20250630145910-0bba51f925b0 h1:a1JzU74qfv/L+sQ/eQ9bzqzltR/gKXM0oXEQveboIQ4=
-deps.dev/util/pypi v0.0.0-20250630145910-0bba51f925b0/go.mod h1:qmA0z/Lsfa1FMtuLd9JmVZLMHR3GBX/EmbM6z1X3EDU=
+deps.dev/util/pypi v0.0.0-20250903005441-604c45d5b44b h1:67FfxwUt82PEMle2FKlW4DZvzcfSODDoTnSGOT1bYtY=
+deps.dev/util/pypi v0.0.0-20250903005441-604c45d5b44b/go.mod h1:qmA0z/Lsfa1FMtuLd9JmVZLMHR3GBX/EmbM6z1X3EDU=
 deps.dev/util/resolve v0.0.0-20250917073939-6ff3dd7d2eea h1:G1Z4ENGQYpmXQWZ5lZhRuy6mWb44pcp30JytYqzvrFk=
 deps.dev/util/resolve v0.0.0-20250917073939-6ff3dd7d2eea/go.mod h1:KTvVyZikz2Vcjl5qOblwBvuAXCkeQKjpO7y754qeyNc=
 deps.dev/util/semver v0.0.0-20250917073939-6ff3dd7d2eea h1:auC4QuBVwiKKgHuyV5OJe7iRA9Bq5qF7Xi5wxs7PdZE=
@@ -217,8 +219,8 @@ github.com/google/go-containerregistry v0.20.6 h1:cvWX87UxxLgaH76b4hIvya6Dzz9qHB
 github.com/google/go-containerregistry v0.20.6/go.mod h1:T0x8MuoAoKX/873bkeSfLD2FAkwCDf9/HZgsFJ02E2Y=
 github.com/google/go-cpy v0.0.0-20211218193943-a9c933c06932 h1:5/4TSDzpDnHQ8rKEEQBjRlYx77mHOvXu08oGchxej7o=
 github.com/google/go-cpy v0.0.0-20211218193943-a9c933c06932/go.mod h1:cC6EdPbj/17GFCPDK39NRarlMI+kt+O60S12cNB5J9Y=
-github.com/google/osv-scalibr v0.3.3-0.20250829011816-004b493f3b78 h1:jNOhXNtWN+jMTuALiQojeRaY6/uoRm1RLY38i4wWWC4=
-github.com/google/osv-scalibr v0.3.3-0.20250829011816-004b493f3b78/go.mod h1:AgqfZegqrMYQk++qV2AR6+HleL8I69ebnxBwbTbYFPU=
+github.com/google/osv-scalibr v0.3.4 h1:YoHviDLM6/FIEfqH1nuLdImmqmg4XGYL0kr0s+6T+sk=
+github.com/google/osv-scalibr v0.3.4/go.mod h1:YeOH2wz0HlccjDbYYYTcX01ZyAuwqhZcpQFV7Cxsrwo=
 github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
 github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -312,8 +314,8 @@ github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU
 github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
 github.com/opencontainers/selinux v1.12.0 h1:6n5JV4Cf+4y0KNXW48TLj5DwfXpvWlxXplUkdTrmPb8=
 github.com/opencontainers/selinux v1.12.0/go.mod h1:BTPX+bjVbWGXw7ZZWUbdENt8w0htPSrlgOOysQaU62U=
-github.com/ossf/osv-schema/bindings/go v0.0.0-20250922001250-9fc1e2b3ee88 h1:iBvKS/UKt2tdEawQnvXH7d2bCZEYN/3kYTtiQyO0HqA=
-github.com/ossf/osv-schema/bindings/go v0.0.0-20250922001250-9fc1e2b3ee88/go.mod h1:/ypmJBpoMvgNp4g93snzyYoyIPmZfLdSiGn/Vq07Dfo=
+github.com/ossf/osv-schema/bindings/go v0.0.0-20250926044009-f6ae0b6bae32 h1:QFuqxEaRdRapDSJYMrl/5vAxYl5ZvIqtWszhuy/EeRs=
+github.com/ossf/osv-schema/bindings/go v0.0.0-20250926044009-f6ae0b6bae32/go.mod h1:/ypmJBpoMvgNp4g93snzyYoyIPmZfLdSiGn/Vq07Dfo=
 github.com/owenrumney/go-sarif/v3 v3.2.3 h1:n6mdX5ugKwCrZInvBsf6WumXmpAe3mbmQXgkXlIq34U=
 github.com/owenrumney/go-sarif/v3 v3.2.3/go.mod h1:1bV7t8SZg7pX41spaDkEUs8/yEjzk9JapztMoX1XNjg=
 github.com/package-url/packageurl-go v0.1.3 h1:4juMED3hHiz0set3Vq3KeQ75KD1avthoXLtmE3I0PLs=
@@ -393,6 +395,8 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
 github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
 github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
 github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
+github.com/tink-crypto/tink-go/v2 v2.4.0 h1:8VPZeZI4EeZ8P/vB6SIkhlStrJfivTJn+cQ4dtyHNh0=
+github.com/tink-crypto/tink-go/v2 v2.4.0/go.mod h1:l//evrF2Y3MjdbpNDNGnKgCpo5zSmvUvnQ4MU+yE2sw=
 github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4=
 github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4=
 github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso=
@@ -486,6 +490,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
 golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
 golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
+golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -624,8 +630,8 @@ modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
 modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
 modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
 modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
-osv.dev/bindings/go v0.0.0-20250922045631-2718b40f69af h1:HPKgvTAAPV/z7ctlbp0+qqqeB8r/eQAJmpoLKi502cc=
-osv.dev/bindings/go v0.0.0-20250922045631-2718b40f69af/go.mod h1:49ptvX6Jf3MhnnzMK7qOjuFxWsLzw7r2F/lTQ+RQjwY=
+osv.dev/bindings/go v0.0.0-20250929041518-3b73304a1688 h1:ZoNfLkmA0fMDPvviJkh0cJKNkZS1+urQDurQ4p4OIjA=
+osv.dev/bindings/go v0.0.0-20250929041518-3b73304a1688/go.mod h1:Q/9axnazyiBRWDN5ruXSGRkH3wrBS5ejQCkflp/VyFg=
 sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
 sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ=
 sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4=
diff --git a/internal/clients/clientimpl/localmatcher/localmatcher.go b/internal/clients/clientimpl/localmatcher/localmatcher.go
index 9416ed07..e173ac23 100644
--- a/internal/clients/clientimpl/localmatcher/localmatcher.go
+++ b/internal/clients/clientimpl/localmatcher/localmatcher.go
@@ -55,21 +55,29 @@ func (matcher *LocalMatcher) MatchVulnerabilities(ctx context.Context, invs []*e
 		}
 
 		pkg := imodels.FromInventory(inv)
+		eco := pkg.Ecosystem().Ecosystem
+
 		if pkg.Ecosystem().IsEmpty() {
 			if pkg.Commit() == "" {
 				// This should never happen, as those results will be filtered out before matching
 				return nil, errors.New("ecosystem is empty and there is no commit hash")
 			}
 
-			// Is a commit based query, skip local scanning
-			results = append(results, []*osvschema.Vulnerability{})
-			// TODO (V2 logging):
-			cmdlogger.Infof("Skipping commit scanning for: %s", pkg.Commit())
+			// matching ecosystem-less versions can only be attempted if we have a version
+			if pkg.Version() == "" {
+				// Is a commit based query, skip local scanning
+				results = append(results, []*osvschema.Vulnerability{})
 
-			continue
+				// TODO (V2 logging):
+				cmdlogger.Infof("Skipping commit scanning for: %s", pkg.Commit())
+
+				continue
+			}
+
+			eco = "GIT"
 		}
 
-		db, err := matcher.loadDBFromCache(ctx, pkg.Ecosystem())
+		db, err := matcher.loadDBFromCache(ctx, eco)
 
 		if err != nil {
 			// no logging here as the loader will have already done that
@@ -87,32 +95,32 @@ func (matcher *LocalMatcher) MatchVulnerabilities(ctx context.Context, invs []*e
 // LoadEcosystem tries to preload the ecosystem into the cache, and returns an error if the ecosystem
 // cannot be loaded.
 func (matcher *LocalMatcher) LoadEcosystem(ctx context.Context, eco osvecosystem.Parsed) error {
-	_, err := matcher.loadDBFromCache(ctx, eco)
+	_, err := matcher.loadDBFromCache(ctx, eco.Ecosystem)
 
 	return err
 }
 
-func (matcher *LocalMatcher) loadDBFromCache(ctx context.Context, eco osvecosystem.Parsed) (*ZipDB, error) {
-	if db, ok := matcher.dbs[eco.Ecosystem]; ok {
+func (matcher *LocalMatcher) loadDBFromCache(ctx context.Context, eco osvschema.Ecosystem) (*ZipDB, error) {
+	if db, ok := matcher.dbs[eco]; ok {
 		return db, nil
 	}
 
-	if matcher.failedDBs[eco.Ecosystem] != nil {
-		return nil, matcher.failedDBs[eco.Ecosystem]
+	if matcher.failedDBs[eco] != nil {
+		return nil, matcher.failedDBs[eco]
 	}
 
-	db, err := NewZippedDB(ctx, matcher.dbBasePath, string(eco.Ecosystem), fmt.Sprintf("%s/%s/all.zip", zippedDBRemoteHost, eco.Ecosystem), matcher.userAgent, !matcher.downloadDB)
+	db, err := NewZippedDB(ctx, matcher.dbBasePath, string(eco), fmt.Sprintf("%s/%s/all.zip", zippedDBRemoteHost, eco), matcher.userAgent, !matcher.downloadDB)
 
 	if err != nil {
-		matcher.failedDBs[eco.Ecosystem] = err
-		cmdlogger.Errorf("could not load db for %s ecosystem: %v", eco.Ecosystem, err)
+		matcher.failedDBs[eco] = err
+		cmdlogger.Errorf("could not load db for %s ecosystem: %v", eco, err)
 
 		return nil, err
 	}
 
 	cmdlogger.Infof("Loaded %s local db from %s", db.Name, db.StoredAt)
 
-	matcher.dbs[eco.Ecosystem] = db
+	matcher.dbs[eco] = db
 
 	return db, nil
 }
diff --git a/internal/scalibrextract/filesystem/vendored/vendored.go b/internal/scalibrextract/filesystem/vendored/vendored.go
index 461efeb7..64f4c4fc 100644
--- a/internal/scalibrextract/filesystem/vendored/vendored.go
+++ b/internal/scalibrextract/filesystem/vendored/vendored.go
@@ -65,7 +65,6 @@ type Config struct {
 	// this is used to avoid duplicate results, once from git scanning, once from vendoredDir scanning
 	ScanGitDir bool
 	OSVClient  *osvdev.OSVClient
-	Disabled   bool
 }
 
 type Extractor struct {
@@ -73,7 +72,6 @@ type Extractor struct {
 	// this is used to avoid duplicate results, once from git scanning, once from vendoredDir scanning
 	ScanGitDir bool
 	OSVClient  *osvdev.OSVClient
-	Disabled   bool
 }
 
 // New returns a new instance of the extractor.
@@ -96,10 +94,6 @@ func (e *Extractor) Requirements() *plugin.Capabilities {
 
 // FileRequired returns true for likely directories to contain vendored c/c++ code
 func (e *Extractor) FileRequired(fapi filesystem.FileAPI) bool {
-	if e.Disabled {
-		return false
-	}
-
 	// Check if parent directory is one of the vendoredLibName
 	// Clean first before Dir call to avoid trailing slashes causing problems
 	parentDir := filepath.Base(filepath.Dir(filepath.Clean(fapi.Path())))
@@ -120,11 +114,6 @@ func (e *Extractor) FileRequired(fapi filesystem.FileAPI) bool {
 // Extract determines the most likely package version from the directory and returns them as
 // commit hash inventory entries
 func (e *Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) (inventory.Inventory, error) {
-	// todo: maybe we should return an error instead? need to double check we're always using FileRequired correctly first
-	if e.Disabled {
-		return inventory.Inventory{}, nil
-	}
-
 	var packages []*extractor.Package
 
 	results, err := e.queryDetermineVersions(ctx, input.Path, input.FS, e.ScanGitDir)
@@ -229,7 +218,6 @@ type configurable interface {
 func (e *Extractor) Configure(config Config) {
 	e.ScanGitDir = config.ScanGitDir
 	e.OSVClient = config.OSVClient
-	e.Disabled = config.Disabled
 }
 
 var _ configurable = &Extractor{}
diff --git a/internal/scalibrextract/vcs/gitrepo/extractor.go b/internal/scalibrextract/vcs/gitrepo/extractor.go
index 8b1972af..4a992268 100644
--- a/internal/scalibrextract/vcs/gitrepo/extractor.go
+++ b/internal/scalibrextract/vcs/gitrepo/extractor.go
@@ -19,17 +19,9 @@ const (
 	Name = "vcs/gitrepo"
 )
 
-type Config struct {
-	IncludeRootGit bool
-	Disabled       bool
-}
-
 // Extractor extracts git repository hashes including submodule hashes.
 // This extractor will not return an error, and will just return no results if we fail to extract
-type Extractor struct {
-	IncludeRootGit bool
-	Disabled       bool
-}
+type Extractor struct{}
 
 func getCommitSHA(repo *git.Repository) (string, error) {
 	head, err := repo.Head()
@@ -89,10 +81,6 @@ func (e *Extractor) Requirements() *plugin.Capabilities {
 
 // FileRequired returns true for git repositories .git dirs
 func (e *Extractor) FileRequired(fapi filesystem.FileAPI) bool {
-	if e.Disabled {
-		return false
-	}
-
 	if filepath.Base(fapi.Path()) != ".git" {
 		return false
 	}
@@ -108,11 +96,6 @@ func (e *Extractor) FileRequired(fapi filesystem.FileAPI) bool {
 
 // Extract extracts git commits from HEAD and from submodules
 func (e *Extractor) Extract(_ context.Context, input *filesystem.ScanInput) (inventory.Inventory, error) {
-	// todo: maybe we should return an error instead? need to double check we're always using FileRequired correctly first
-	if e.Disabled {
-		return inventory.Inventory{}, nil
-	}
-
 	// The input path is the .git directory, but git.PlainOpen expects the actual directory containing the .git dir.
 	// So call filepath.Dir to get the parent path
 	// Assume this is fully on a real filesystem
@@ -124,14 +107,12 @@ func (e *Extractor) Extract(_ context.Context, input *filesystem.ScanInput) (inv
 
 	var inv inventory.Inventory
 
-	if e.IncludeRootGit {
-		commitSHA, err := getCommitSHA(repo)
+	commitSHA, err := getCommitSHA(repo)
 
-		// If error is not nil, then ignore this and continue, as it is not fatal.
-		// The error could be because there are no commits in the repository
-		if err == nil {
-			inv.Packages = append(inv.Packages, createCommitQueryInventory(commitSHA, input.Path))
-		}
+	// If error is not nil, then ignore this and continue, as it is not fatal.
+	// The error could be because there are no commits in the repository
+	if err == nil {
+		inv.Packages = append(inv.Packages, createCommitQueryInventory(commitSHA, input.Path))
 	}
 
 	// If we can't get submodules, just return with what we have.
@@ -159,22 +140,3 @@ func (e *Extractor) Ecosystem(_ *extractor.Package) string {
 }
 
 var _ filesystem.Extractor = &Extractor{}
-
-type configurable interface {
-	Configure(config Config)
-}
-
-func (e *Extractor) Configure(config Config) {
-	e.IncludeRootGit = config.IncludeRootGit
-	e.Disabled = config.Disabled
-}
-
-var _ configurable = &Extractor{}
-
-func Configure(plug plugin.Plugin, config Config) {
-	us, ok := plug.(configurable)
-
-	if ok {
-		us.Configure(config)
-	}
-}
diff --git a/internal/utility/vulns/vulnerability.go b/internal/utility/vulns/vulnerability.go
index b67b5fb1..f37128e3 100644
--- a/internal/utility/vulns/vulnerability.go
+++ b/internal/utility/vulns/vulnerability.go
@@ -125,8 +125,26 @@ func AffectsEcosystem(v osvschema.Vulnerability, ecosystemAffected osvecosystem.
 	return false
 }
 
+func hasGitRangeForRepo(affected osvschema.Affected, repo string) bool {
+	for _, r := range affected.Ranges {
+		if r.Type == "GIT" && r.Repo == repo {
+			return true
+		}
+	}
+
+	return false
+}
+
 func IsAffected(v osvschema.Vulnerability, pkg imodels.PackageInfo) bool {
 	for _, affected := range v.Affected {
+		// assume we're dealing with a git-source package whose name is the git repository, and that the version is the tag
+		// the underlying commit has been resolved to (somehow), meaning we can check if it's in the versions listed by the advisory
+		if pkg.Ecosystem().IsEmpty() && pkg.Commit() != "" && pkg.Version() != "" {
+			if hasGitRangeForRepo(affected, pkg.Name()) && slices.Contains(affected.Versions, pkg.Version()) {
+				return true
+			}
+		}
+
 		// Assume vulnerability has already been validated
 		if osvecosystem.MustParse(affected.Package.Ecosystem).Equal(pkg.Ecosystem()) &&
 			affected.Package.Name == pkg.Name() {
diff --git a/pkg/osvscanner/osvscanner.go b/pkg/osvscanner/osvscanner.go
index ea00728e..ca440746 100644
--- a/pkg/osvscanner/osvscanner.go
+++ b/pkg/osvscanner/osvscanner.go
@@ -111,6 +111,7 @@ var ErrVulnerabilitiesFound = errors.New("vulnerabilities found")
 var ErrAPIFailed = errors.New("API query failed")
 
 func initializeExternalAccessors(actions ScannerActions) (ExternalAccessors, error) {
+	ctx := context.Background()
 	externalAccessors := ExternalAccessors{
 		DependencyClients: map[osvschema.Ecosystem]resolve.Client{},
 	}
@@ -165,7 +166,7 @@ func initializeExternalAccessors(actions ScannerActions) (ExternalAccessors, err
 	}
 
 	// --- Transitive Scanning Clients ---
-	externalAccessors.MavenRegistryAPIClient, err = datasource.NewMavenRegistryAPIClient(datasource.MavenRegistry{
+	externalAccessors.MavenRegistryAPIClient, err = datasource.NewMavenRegistryAPIClient(ctx, datasource.MavenRegistry{
 		URL:             actions.MavenRegistry,
 		ReleasesEnabled: true,
 	}, "")
@@ -177,7 +178,7 @@ func initializeExternalAccessors(actions ScannerActions) (ExternalAccessors, err
 	if !actions.NativeDataSource {
 		externalAccessors.DependencyClients[osvschema.EcosystemMaven], err = resolution.NewDepsDevClient(depsdev.DepsdevAPI, "osv-scanner_scan/"+version.OSVVersion)
 	} else {
-		externalAccessors.DependencyClients[osvschema.EcosystemMaven], err = resolution.NewMavenRegistryClient(actions.MavenRegistry, "")
+		externalAccessors.DependencyClients[osvschema.EcosystemMaven], err = resolution.NewMavenRegistryClient(ctx, actions.MavenRegistry, "")
 	}
 
 	// We only support native registry client for PyPI.
diff --git a/pkg/osvscanner/scan.go b/pkg/osvscanner/scan.go
index 7077f454..db357b1c 100644
--- a/pkg/osvscanner/scan.go
+++ b/pkg/osvscanner/scan.go
@@ -46,18 +46,10 @@ func configurePlugins(plugins []plugin.Plugin, accessors ExternalAccessors, acti
 			})
 		}
 
-		// todo: the "disabled" aspect should probably be worked into the extractor being present in the first place
-		//  since "IncludeRootGit" is always true
-		gitrepo.Configure(plug, gitrepo.Config{
-			IncludeRootGit: actions.IncludeGitRoot,
-			Disabled:       !actions.IncludeGitRoot,
-		})
-
 		vendored.Configure(plug, vendored.Config{
 			// Only attempt to vendor check git directories if we are not skipping scanning root git directories
 			ScanGitDir: !actions.IncludeGitRoot,
 			OSVClient:  accessors.OSVDevClient,
-			Disabled:   accessors.OSVDevClient == nil,
 		})
 	}
 }
@@ -67,6 +59,14 @@ func getPlugins(defaultPlugins []string, accessors ExternalAccessors, actions Sc
 		actions.PluginsEnabled = append(actions.PluginsEnabled, defaultPlugins...)
 	}
 
+	if !actions.IncludeGitRoot {
+		actions.PluginsDisabled = append(actions.PluginsDisabled, gitrepo.Name)
+	}
+
+	if accessors.OSVDevClient == nil {
+		actions.PluginsDisabled = append(actions.PluginsDisabled, vendored.Name)
+	}
+
 	plugins := scalibrplugin.Resolve(actions.PluginsEnabled, actions.PluginsDisabled)
 
 	configurePlugins(plugins, accessors, actions)



Test patch:
diff --git a/cmd/osv-scanner/scan/source/command_test.go b/cmd/osv-scanner/scan/source/command_test.go
index 7f404552..63e9d5db 100644
--- a/cmd/osv-scanner/scan/source/command_test.go
+++ b/cmd/osv-scanner/scan/source/command_test.go
@@ -972,6 +972,31 @@ func TestCommand_LocalDatabases_AlwaysOffline(t *testing.T) {
 	}
 }
 
+func TestCommand_CommitSupport(t *testing.T) {
+	t.Parallel()
+
+	tests := []testcmd.Case{
+		{
+			Name: "online_uses_git_commits",
+			Args: []string{"", "source", "--lockfile", "osv-scanner:./testdata/locks-git/osv-scanner.json"},
+			Exit: 1,
+		},
+		{
+			Name: "offline_uses_git_tags",
+			Args: []string{"", "source", "--offline", "--download-offline-databases", "--lockfile", "osv-scanner:./testdata/locks-git/osv-scanner.json"},
+			Exit: 1,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.Name, func(t *testing.T) {
+			t.Parallel()
+
+			testcmd.RunAndMatchSnapshots(t, tt)
+		})
+	}
+}
+
 func TestCommand_Licenses(t *testing.T) {
 	t.Parallel()
 
diff --git a/cmd/osv-scanner/scan/source/testdata/locks-git/osv-scanner.json b/cmd/osv-scanner/scan/source/testdata/locks-git/osv-scanner.json
new file mode 100644
index 00000000..3aa6265f
--- /dev/null
+++ b/cmd/osv-scanner/scan/source/testdata/locks-git/osv-scanner.json
@@ -0,0 +1,40 @@
+{
+  "results": [
+    {
+      "packages": [
+        {
+          "//1": "version and commit are the same, so rust-openssl advisories should be reported",
+          "//2": "note online reports CVE-2023-6180 as well due to matching commits for an implicit fork",
+          "package": {
+            "name": "https://github.com/sfackler/rust-openssl",
+            "commit": "0f428d190410263e4daa65b917c0e84707a9c0ef",
+            "version": "openssl-v0.8.1"
+          }
+        },
+        {
+          "//1": "repo is different to the advisory, so only online checking will report anything",
+          "package": {
+            "name": "https://github.com/sfackler-fork/rust-openssl",
+            "commit": "3b064fdb022912bbb98f5b8d9d111aeb6fec8f79",
+            "version": "openssl-v0.10.23"
+          }
+        },
+        {
+          "//1": "no version, so only online checking will report anything",
+          "package": {
+            "name": "https://github.com/openssl/openssl",
+            "commit": "45fda76bc1b9fd74d10e85e0ce9b65a12dcc58b0"
+          }
+        },
+        {
+          "//1": "version is for 3.5.0 which is vulnerable to CVE-2025-3416, but commit is for 3.5.1 which is not",
+          "package": {
+            "name": "https://github.com/openssl/openssl",
+            "commit": "aea7aaf2abb04789f5868cbabec406ea43aa84bf",
+            "version": "openssl-3.5.0"
+          }
+        }
+      ]
+    }
+  ]
+}
diff --git a/internal/scalibrextract/vcs/gitrepo/extractor_test.go b/internal/scalibrextract/vcs/gitrepo/extractor_test.go
index 93411309..6a5117d7 100644
--- a/internal/scalibrextract/vcs/gitrepo/extractor_test.go
+++ b/internal/scalibrextract/vcs/gitrepo/extractor_test.go
@@ -49,9 +49,7 @@ func TestExtractor_Extract(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.Name, func(t *testing.T) {
 			t.Parallel()
-			extr := gitrepo.Extractor{
-				IncludeRootGit: true,
-			}
+			extr := gitrepo.Extractor{}
 			parent := filepath.Dir(tt.InputConfig.Path)
 			err := os.Rename(path.Join(parent, "git-hidden"), path.Join(parent, ".git"))
 			if err != nil {