Repository: google/osv-scanner
Pull request #579 (2023-10-08 15:39:37)

chore(deps): update dependency jekyll-feed to v0.17.0
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [jekyll-feed](https://togithub.com/jekyll/jekyll-feed) | `0.15.1` -> `0.17.0` | [![age](https://developer.mend.io/api/mc/badges/age/rubygems/jekyll-feed/0.17.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/rubygems/jekyll-feed/0.17.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/rubygems/jekyll-feed/0.15.1/0.17.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/rubygems/jekyll-feed/0.15.1/0.17.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>jekyll/jekyll-feed (jekyll-feed)</summary>

### [`v0.17.0`](https://togithub.com/jekyll/jekyll-feed/blob/HEAD/History.markdown#0170--2022-10-14)

[Compare Source](https://togithub.com/jekyll/jekyll-feed/compare/v0.16.0...v0.17.0)

##### Documentation

-   Update CI status badge ([#&#8203;363](https://togithub.com/jekyll/jekyll-feed/issues/363))

##### Development Fixes

-   Add Ruby 3.1 to the CI matrix ([#&#8203;365](https://togithub.com/jekyll/jekyll-feed/issues/365))

##### Minor Enhancements

-   Allow disabling of jekyll-feed while in development ([#&#8203;370](https://togithub.com/jekyll/jekyll-feed/issues/370))

### [`v0.16.0`](https://togithub.com/jekyll/jekyll-feed/blob/HEAD/History.markdown#0160--2022-01-03)

[Compare Source](https://togithub.com/jekyll/jekyll-feed/compare/v0.15.1...v0.16.0)

##### Minor Enhancements

-   Add support for `page.description` in front matter to become entry `<summary>` ([#&#8203;297](https://togithub.com/jekyll/jekyll-feed/issues/297))

##### Bug Fixes

-   Fold private methods into the `:render` method as local variables ([#&#8203;327](https://togithub.com/jekyll/jekyll-feed/issues/327))
-   Check `post.categories` instead of `post.category` ([#&#8203;357](https://togithub.com/jekyll/jekyll-feed/issues/357))
-   Switched xml_escape for `<![CDATA[]]>` for post content ([#&#8203;332](https://togithub.com/jekyll/jekyll-feed/issues/332))

##### Development Fixes

-   Add Ruby 3.0 to CI ([#&#8203;337](https://togithub.com/jekyll/jekyll-feed/issues/337))
-   Lock RuboCop to v1.18.x ([#&#8203;348](https://togithub.com/jekyll/jekyll-feed/issues/348))
-   Add workflow to release gem via GH Action ([#&#8203;355](https://togithub.com/jekyll/jekyll-feed/issues/355))

##### Documentation

-   Use `.atom` extension in documented examples since we write an Atom feed ([#&#8203;359](https://togithub.com/jekyll/jekyll-feed/issues/359))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "before 6am on monday" in timezone Australia/Sydney, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/google/osv-scanner).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4wLjMiLCJ1cGRhdGVkSW5WZXIiOiIzNy4wLjMiLCJ0YXJnZXRCcmFuY2giOiJtYWluIn0=-->


codecov-commenter: ## [Codecov](https://app.codecov.io/gh/google/osv-scanner/pull/579?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) Report
> Merging [#579](https://app.codecov.io/gh/google/osv-scanner/pull/579?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) (28f167b) into [main](https://app.codecov.io/gh/google/osv-scanner/commit/4d86a90585bdbea1634b81c9b709a5a187a3c93b?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) (4d86a90) will **not change** coverage.
> The diff coverage is `n/a`.

```diff
@@           Coverage Diff           @@
##             main     #579   +/-   ##
=======================================
  Coverage   80.14%   80.14%           
=======================================
  Files          77       77           
  Lines        5314     5314           
=======================================
  Hits         4259     4259           
  Misses        881      881           
  Partials      174      174           
```





Patch:
diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml
index d9eed7f..9b0a8d1 100644
--- a/.github/workflows/checks.yml
+++ b/.github/workflows/checks.yml
@@ -32,7 +32,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Check out code
-        uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
         with:
           persist-credentials: false
       - name: Set up Go
@@ -51,7 +51,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out code
-        uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
         with:
           persist-credentials: false
       - name: Set up Go
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 3d61bcb..42875c9 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -40,11 +40,11 @@ jobs:
 
     steps:
       - name: Checkout repository
-        uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
 
       # Initializes the CodeQL tools for scanning.
       - name: Initialize CodeQL
-        uses: github/codeql-action/init@ddccb873888234080b77e9bc2d4764d5ccaaccf9 # v2.21.9
+        uses: github/codeql-action/init@0116bc2df50751f9724a2e35ef1f24d22f90e4e1 # v2.22.3
         with:
           languages: ${{ matrix.language }}
           # If you wish to specify custom queries, you can do so here or in a config file.
@@ -55,7 +55,7 @@ jobs:
       # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).
       # If this step fails, then you should remove it and run the build manually (see below)
       - name: Autobuild
-        uses: github/codeql-action/autobuild@ddccb873888234080b77e9bc2d4764d5ccaaccf9 # v2.21.9
+        uses: github/codeql-action/autobuild@0116bc2df50751f9724a2e35ef1f24d22f90e4e1 # v2.22.3
 
       # ℹ️ Command-line programs to run using the OS shell.
       # 📚 https://git.io/JvXDl
@@ -69,4 +69,4 @@ jobs:
       #   make release
 
       - name: Perform CodeQL Analysis
-        uses: github/codeql-action/analyze@ddccb873888234080b77e9bc2d4764d5ccaaccf9 # v2.21.9
+        uses: github/codeql-action/analyze@0116bc2df50751f9724a2e35ef1f24d22f90e4e1 # v2.22.3
diff --git a/.github/workflows/goreleaser.yml b/.github/workflows/goreleaser.yml
index ae108cc..eb5f8c7 100644
--- a/.github/workflows/goreleaser.yml
+++ b/.github/workflows/goreleaser.yml
@@ -25,7 +25,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Check out code
-        uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
         with:
           persist-credentials: false
       - name: Set up Go
@@ -44,7 +44,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out code
-        uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
         with:
           persist-credentials: false
       - name: Set up Go
@@ -70,7 +70,7 @@ jobs:
       DOCKER_CLI_EXPERIMENTAL: "enabled"
     steps:
       - name: Checkout
-        uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
         with:
           fetch-depth: 0
       - name: Set up Go
diff --git a/.github/workflows/link-check-on-push.yml b/.github/workflows/link-check-on-push.yml
index e5c6d3c..62804c8 100644
--- a/.github/workflows/link-check-on-push.yml
+++ b/.github/workflows/link-check-on-push.yml
@@ -7,7 +7,7 @@ jobs:
   markdown-link-check:
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+    - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
     - uses: gaurav-nelson/github-action-markdown-link-check@a996638015fbc9ef96beef1a41bbad7df8e06154
       with:
         use-quiet-mode: "yes"
diff --git a/.github/workflows/link-check.yml b/.github/workflows/link-check.yml
index c8e04b4..a83338c 100644
--- a/.github/workflows/link-check.yml
+++ b/.github/workflows/link-check.yml
@@ -9,7 +9,7 @@ jobs:
   markdown-link-check:
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+    - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
     - uses: gaurav-nelson/github-action-markdown-link-check@a996638015fbc9ef96beef1a41bbad7df8e06154
       with:
         use-quiet-mode: "yes"
diff --git a/.github/workflows/osv-scanner-pr.yml b/.github/workflows/osv-scanner-pr.yml
index 48a0ce3..09c9c98 100644
--- a/.github/workflows/osv-scanner-pr.yml
+++ b/.github/workflows/osv-scanner-pr.yml
@@ -20,9 +20,15 @@ on:
   merge_group:
     branches: [ main ]
 
-# Declare default permissions as read only.
-permissions: read-all
-
 jobs:
   scan-pr:
     uses: "./.github/workflows/osv-scanner-reusable-pr.yml"
+    with:
+      # Just scan the root directory and docs, since everything else is fixtures
+      scan-args: |-
+          --skip-git
+          ./
+          ./docs/
+    permissions:
+      security-events: write
+      contents: read
diff --git a/.github/workflows/osv-scanner-reusable-pr.yml b/.github/workflows/osv-scanner-reusable-pr.yml
index ba0e4aa..8b4fc77 100644
--- a/.github/workflows/osv-scanner-reusable-pr.yml
+++ b/.github/workflows/osv-scanner-reusable-pr.yml
@@ -14,6 +14,10 @@
 
 name: OSV-Scanner PR scanning reusable
 
+permissions:
+  contents: read
+  security-events: write
+
 on:
   workflow_call:
     inputs:
@@ -24,12 +28,16 @@ on:
           -r
           --skip-git
           ./
+      results-file-name:
+        description: "File name of the result SARIF file"
+        type: string
+        default: results.sarif
 
 jobs:
   scan-pr:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+      - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
         with:
           fetch-depth: 0
           # Do persist credentials, as we need it for the git checkout later
@@ -57,7 +65,7 @@ jobs:
         uses: google/osv-scanner/actions/reporter@main
         with:
           scan-args: |-
-            --output=final-results.sarif
+            --output=${{ inputs.results-file-name }}
             --old=old-results.json
             --new=new-results.json
             --gh-annotations=true
@@ -68,7 +76,7 @@ jobs:
         uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
         with:
           name: SARIF file
-          path: final-results.sarif
+          path: ${{ inputs.results-file-name }}
           retention-days: 5
       - name: "Upload old scan json results"
         if: '!cancelled()'
@@ -87,6 +95,6 @@ jobs:
       # Upload the results to GitHub's code scanning dashboard.
       - name: "Upload to code-scanning"
         if: '!cancelled()'
-        uses: github/codeql-action/upload-sarif@ddccb873888234080b77e9bc2d4764d5ccaaccf9 # v2.21.9
+        uses: github/codeql-action/upload-sarif@0116bc2df50751f9724a2e35ef1f24d22f90e4e1 # v2.22.3
         with:
-          sarif_file: final-results.sarif
+          sarif_file: ${{ inputs.results-file-name }}
diff --git a/.github/workflows/osv-scanner-reusable.yml b/.github/workflows/osv-scanner-reusable.yml
index 5d55b21..45a8471 100644
--- a/.github/workflows/osv-scanner-reusable.yml
+++ b/.github/workflows/osv-scanner-reusable.yml
@@ -14,6 +14,10 @@
 
 name: OSV-Scanner scanning reusable
 
+permissions:
+  contents: read
+  security-events: write
+
 on:
   workflow_call:
     inputs:
@@ -28,12 +32,25 @@ on:
         description: "File name of the result SARIF file"
         type: string
         default: results.sarif
+      download-artifact:
+        description: "Optional artifact to download for scanning"
+        required: false
+        default: ""
+        type: string
 
 jobs:
-  scan-scheduled:
+  osv-scan:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+        with:
+          persist-credentials: false
+      - name: "Download custom artifact if specified"
+        uses: actions/download-artifact@v3
+        if: "${{ inputs.download-artifact != '' }}"
+        with:
+          name: "${{ inputs.download-artifact }}"
+          path: "./"
       - name: "Run scanner"
         uses: google/osv-scanner/actions/scanner@main
         with:
@@ -41,6 +58,7 @@ jobs:
             --output=results.json
             --format=json
             ${{ inputs.scan-args }}
+        continue-on-error: true
       - name: "Run osv-scanner-reporter"
         uses: google/osv-scanner/actions/reporter@main
         with:
@@ -60,7 +78,7 @@ jobs:
       # Upload the results to GitHub's code scanning dashboard.
       - name: "Upload to code-scanning"
         if: '!cancelled()'
-        uses: github/codeql-action/upload-sarif@ddccb873888234080b77e9bc2d4764d5ccaaccf9 # v2.21.9
+        uses: github/codeql-action/upload-sarif@0116bc2df50751f9724a2e35ef1f24d22f90e4e1 # v2.22.3
         with:
           sarif_file: ${{ inputs.results-file-name }}
 
diff --git a/.github/workflows/osv-scanner-scheduled.yml b/.github/workflows/osv-scanner-scheduled.yml
index 27ad76b..8704810 100644
--- a/.github/workflows/osv-scanner-scheduled.yml
+++ b/.github/workflows/osv-scanner-scheduled.yml
@@ -20,12 +20,18 @@ on:
   push:
     branches: [ "main" ]
 
-permissions:
-  # Require writing security events to upload SARIF file to security tab
-  security-events: write
-  # Only need to read contents
-  contents: read
-
 jobs:
   scan-scheduled:
     uses: "./.github/workflows/osv-scanner-reusable.yml"
+    with:
+      # Just scan the root directory and docs, since everything else is fixtures
+      scan-args: |-
+          --skip-git
+          ./
+          ./docs/
+    permissions:
+      # Require writing security events to upload SARIF file to security tab
+      security-events: write
+      # Read commit contents
+      contents: read
+
diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml
index 30ee9fa..a983bfb 100644
--- a/.github/workflows/scorecards.yml
+++ b/.github/workflows/scorecards.yml
@@ -32,12 +32,12 @@ jobs:
 
     steps:
       - name: "Checkout code"
-        uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
         with:
           persist-credentials: false
 
       - name: "Run analysis"
-        uses: ossf/scorecard-action@08b4669551908b1024bb425080c797723083c031 # v2.2.0
+        uses: ossf/scorecard-action@483ef80eb98fb506c348f7d62e28055e49fe2398 # v2.3.0
         with:
           results_file: results.sarif
           results_format: sarif
@@ -67,6 +67,6 @@ jobs:
 
       # Upload the results to GitHub's code scanning dashboard.
       - name: "Upload to code-scanning"
-        uses: github/codeql-action/upload-sarif@ddccb873888234080b77e9bc2d4764d5ccaaccf9 # v2.21.9
+        uses: github/codeql-action/upload-sarif@0116bc2df50751f9724a2e35ef1f24d22f90e4e1 # v2.22.3
         with:
           sarif_file: results.sarif
diff --git a/Dockerfile b/Dockerfile
index 9c4f255..fc6d330 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:4bc6541af94a67d9dcabba9826c36e4e9497dacf4e8755ac503000b6ff75318f AS builder
+FROM golang:alpine@sha256:926f7f7e1ab8509b4e91d5ec6d5916ebb45155b0c8920291ba9f361d65385806 AS builder
 
 WORKDIR /src
 COPY ./go.mod ./go.sum ./
diff --git a/action.dockerfile b/action.dockerfile
index 0b78adc..d90fe41 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:4bc6541af94a67d9dcabba9826c36e4e9497dacf4e8755ac503000b6ff75318f
+FROM golang:alpine@sha256:926f7f7e1ab8509b4e91d5ec6d5916ebb45155b0c8920291ba9f361d65385806
 
 RUN mkdir /src
 WORKDIR /src
diff --git a/cmd/osv-scanner/fixtures/locks-insecure/osv-scanner-flutter-deps.json b/cmd/osv-scanner/fixtures/locks-insecure/osv-scanner-flutter-deps.json
new file mode 100644
index 0000000..e70711e
--- /dev/null
+++ b/cmd/osv-scanner/fixtures/locks-insecure/osv-scanner-flutter-deps.json
@@ -0,0 +1,38 @@
+{
+  "results": [
+    {
+      "packageSource": {
+        "path": "/path/to/engine/DEPS",
+        "type": "lockfile"
+      },
+      "packages": [
+        {
+          "package": {
+            "name": "https://github.com/flutter/buildroot.git",
+            "commit": "5d60bd2eb4642b64d00c845e5ca9f1ea41fd6db6"
+          }
+        },
+        {
+          "package": {
+            "name": "https://github.com/brendan-duncan/archive.git",
+            "commit": "9de7a0544457c6aba755ccb65abb41b0dc1db70d"
+          }
+        }
+      ]
+    },
+    {
+      "packageSource": {
+        "path": "/path/to/engine/third_party/accessibility/README.md",
+        "type": "lockfile"
+      },
+      "packages": [
+        {
+          "package": {
+            "name": "https://chromium.googlesource.com/chromium/src",
+            "commit": "4579d5538f06c5ef615a15bc67ebb9ac0523a973"
+          }
+        }
+      ]
+    }
+  ]
+}
diff --git a/cmd/osv-scanner/fixtures/locks-many/osv-scanner.toml b/cmd/osv-scanner/fixtures/locks-many/osv-scanner.toml
index 5cfb2dc..741cb9c 100644
--- a/cmd/osv-scanner/fixtures/locks-many/osv-scanner.toml
+++ b/cmd/osv-scanner/fixtures/locks-many/osv-scanner.toml
@@ -2,3 +2,7 @@
 id = "GHSA-whgm-jr23-g3j9"
 # ignore_until = 2022-11-09
 reason = "Test manifest file"
+
+[[IgnoredVulns]]
+id = "CVE-2022-48174"
+reason = "Test manifest file (alpine.cdx.xml)"
diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock
index e968ced..ca4d259 100644
--- a/docs/Gemfile.lock
+++ b/docs/Gemfile.lock
@@ -30,7 +30,7 @@ GEM
       faraday-net_http (>= 2.0, < 3.1)
       ruby2_keywords (>= 0.0.4)
     faraday-net_http (3.0.2)
-    ffi (1.16.2)
+    ffi (1.16.3)
     forwardable-extended (2.6.0)
     gemoji (3.0.1)
     github-pages (228)
diff --git a/docs/github-action.md b/docs/github-action.md
index d5d920e..4ee0a94 100644
--- a/docs/github-action.md
+++ b/docs/github-action.md
@@ -6,17 +6,135 @@ nav_order: 6
 ---
 
 # GitHub Action
-
 {: .no_toc }
 
+<details open markdown="block">
+  <summary>
+    Table of contents
+  </summary>
+  {: .text-delta }
+- TOC
+{:toc}
+</details>
+
 OSV-Scanner is offered as a GitHub Action. We currently have two different GitHub Actions:
 
-1. An action that performs a vulnerability scan on a [regular schedule](./github-action.md#scheduled-scans).
-2. An action that triggers a scan with each [pull request](./github-action.md#scans-on-prs) and will only check for new vulnerabilities introduced through the pull request.
+1. An action that triggers a scan with each [pull request](./github-action.md#scans-on-prs) and will only check for new vulnerabilities introduced through the pull request.
+2. An action that performs a single vulnerability scan, which can be configured to scan on a [regular schedule](./github-action.md#scheduled-scans), or used as a check [on releases](./github-action.md#scan-on-release) to prevent releasing with known vulnerabilities in dependencies.
+
+## Scans on PRs
+
+Scanning your project on each pull request can help you keep vulnerabilities out of your project. This GitHub Action compares a vulnerability scan of the target branch to a vulnerability scan of the feature branch, and will fail if there are new vulnerabilities found which doesn't exist in the target branch. You will be notified of any new vulnerabilities introduced through the feature branch. You can also choose to [prevent merging](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches#require-status-checks-before-merging) if new vulnerabilities are introduced through the feature branch.
+
+### Instructions
+
+In your project repository, create a new file `.github/workflows/osv-scanner-pr.yml`.
+
+Include the following in the [`osv-scanner-pr.yml`](https://github.com/google/osv-scanner/blob/main/.github/workflows/osv-scanner-pr.yml) file:
+
+```yml
+name: OSV-Scanner PR Scan
+
+# Change "main" to your default branch if you use a different name, i.e. "master"
+on:
+  pull_request:
+    branches: [ main ]
+  merge_group:
+    branches: [ main ]
+
+# Declare default permissions as read only.
+permissions: read-all
+
+jobs:
+  scan-pr:
+    uses: "google/osv-scanner/.github/workflows/osv-scanner-reusable-pr.yml@main"
+```
+
+### View results
+
+Results may be viewed by clicking on the details of the failed action, either from your project's actions tab or directly on the PR. Results are also included in GitHub annotations on the "Files changed" tab for the PR.
+
+### Customization
+
+`osv-scanner-reusable.yml` takes two optional inputs:
+
+- `scan-args`: This value is passed to `osv-scanner` CLI after being split by each line. See the [usage](./usage) page for the available options.
+  Importantly `--format` and `--output` flags are already set by the reusable workflow and should not be overridden here.
+  Default:
+  ```bash
+    --recursive # Recursively scan subdirectories
+    --skip-git=true # Skip commit scanning to focus on dependencies
+    ./ # Start the scan from the root of the repository
+  ```
+- `results-file-name`: This is the name of the final SARIF file uploaded to Github.
+  Default: `results.sarif`
+- `download-artifact`: Optional artifact to download for scanning. Can be used if you need to do some preprocessing to prepare the lockfiles for scanning.
+  If the file names in the artifact are not standard lockfile names, make sure to add custom scan-args to specify the lockfile type and path (see [specify lockfiles](./usage#specify-lockfiles)).
+
+<details markdown="block">
+<summary>
+Examples
+</summary>
+
+##### Scan specific lockfiles
+```yml
+jobs:
+  scan-pr:
+    uses: "google/osv-scanner/.github/workflows/osv-scanner-reusable.yml"
+    with:
+      scan-args: |-
+        ./path/to/lockfile1
+        requirements.txt:./path/to/python-lockfile2.txt
+```
+##### Default arguments
+```yml
+jobs:
+  scan-pr:
+    uses: "google/osv-scanner/.github/workflows/osv-scanner-reusable.yml"
+    with:
+      scan-args: |-
+        --recursive
+        --skip-git=true
+        ./
+```
+
+##### Using download-artifact input to support preprocessing
+```yml
+jobs:
+  extract-deps:
+    name: Extract Dependencies
+    # ...
+    steps:
+      # ... Steps to extract your dependencies
+      - name: "upload osv-scanner deps" # Upload the deps
+        uses: actions/upload-artifact@v4
+        with:
+          name: converted-OSV-Scanner-deps
+          path: osv-scanner-deps.json
+          retention-days: 2
+  vuln-scan:
+    name: Vulnerability scanning
+    # makes sure the extraction step is completed before running the scanner
+    needs:
+      extract-deps
+    uses: "google/osv-scanner/.github/workflows/osv-scanner-reusable.yml@main"
+    with:
+      # Download the artifact uploaded in extract-deps step
+      download-artifact: converted-OSV-Scanner-deps
+      # Scan only the file inside the uploaded artifact
+      scan-args: |-
+        --lockfile=osv-scanner:osv-scanner-deps.json
+    permissions:
+      # Needed to upload the SARIF results to code-scanning dashboard.
+      security-events: write
+      contents: read
+```
+
+</details>
 
 ## Scheduled scans
 
-Regularly scanning your project for vulnerabilities can alert you to new vulnerabilities in your dependency tree. This GitHub Action will scan your project on a set schedule and report all known vulnerabilities.
+Regularly scanning your project for vulnerabilities can alert you to new vulnerabilities in your dependency tree. This GitHub Action will scan your project on a set schedule and report all known vulnerabilities. If vulnerabilities are found the action will return a failed status.
 
 ### Instructions
 
@@ -47,40 +165,55 @@ jobs:
 
 As written, the scanner will run on 12:12 pm UTC every Monday. You can change the schedule by following the instructions [here](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#schedule).
 
-### View results
+### Customization
 
-Maintainers can review results of the scan by navigating to their project's security > code scanning tab. Vulnerability details can also be viewed by clicking on the details of the failed action.
+`osv-scanner-reusable-pr.yml` has the same customization options as `osv-scanner-reusable.yml`, which is described [here](./github-action.md#customization).
 
-## Scans on PRs
+### View results
 
-Scanning your project on each pull request can help you keep vulnerabilities out of your project. This GitHub Action compares a vulnerability scan of the main branch to a vulnerability scan of the feature branch. You will be notified of any new vulnerabilities introduced through the feature branch. You can also choose to [prevent merging](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches#require-status-checks-before-merging) if new vulnerabilities are introduced through the feature branch.
+Maintainers can review results of the scan by navigating to their project's `security > code scanning` tab. Vulnerability details can also be viewed by clicking on the details of the failed action.
 
-### Instructions
 
-In your project repository, create a new file `.github/workflows/osv-scanner-pr.yml`.
+## Scan on release
 
-Include the following in the [`osv-scanner-pr.yml`](https://github.com/google/osv-scanner/blob/main/.github/workflows/osv-scanner-pr.yml) file:
+Here is a example of blocking on release, though the actual implementation will heavily depend on your specific release process.
 
 ```yml
-name: OSV-Scanner PR Scan
+name: Go Release Process
 
-# Change "main" to your default branch if you use a different name, i.e. "master"
 on:
-  pull_request:
-    branches: [ main ]
-  merge_group:
-    branches: [ main ]
+  push:
+    tags:
+      - "*" # triggers only if push new tag version, like `0.8.4` or else
 
-# Declare default permissions as read only.
-permissions: read-all
+permissions:
+  contents: read # to fetch code (actions/checkout)
 
 jobs:
-  scan-pr:
-    uses: "google/osv-scanner/.github/workflows/osv-scanner-reusable-pr.yml@main"
+  osv-scan:
+    uses: google/osv-scanner/.github/workflows/osv-scanner-reusable.yml
+    with:
+      # Only scan the top level go.mod file without recursively scanning directories since
+      # this is pipeline is about releasing the go module and binary
+      scan-args: |-
+        --skip-git
+        ./
+    permissions:
+      # Require writing security events to upload SARIF file to security tab
+      security-events: write
+  tests:
+    name: Run unit tests
+    ...
+  release:
+    needs: # Needs both tests and osv-scan to pass
+      - tests
+      - osv-scan
+    # Your actual release steps
+    steps:
+      ...
 ```
 
 ### View results
 
-Results may be viewed by clicking on the details of the failed action, either from your project's actions tab or directly on the PR. Results are also included in GitHub annotations on the "Files changed" tab for the PR.
+Results may be viewed by clicking on the details of the failed release action from the action tab.
 
-Results are also available to maintainers by navigating to their project's security > code scanning tab.
diff --git a/docs/output.md b/docs/output.md
index c4b4dde..9c56955 100644
--- a/docs/output.md
+++ b/docs/output.md
@@ -196,6 +196,161 @@ osv-scanner --format json -L path/to/lockfile > /path/to/file.json
 </details>
 
 
+---
+
+### SARIF
+
+```bash
+osv-scanner --format sarif your/project/dir
+```
+
+Outputs the result in the [SARIF](https://sarifweb.azurewebsites.net/) v2.1.0 format. Each vulnerability (grouped by aliases) is a separate rule, and each package containing a vulnerable dependency is a rule violation. The help text within the SARIF report contains detailed information about the vulnerability and remediation instructions for how to resolve it.
+
+<details markdown="1">
+<summary><b>Sample SARIF output</b></summary>
+
+```json
+{
+  "version": "2.1.0",
+  "$schema": "https://json.schemastore.org/sarif-2.1.0.json",
+  "runs": [
+    {
+      "tool": {
+        "driver": {
+          "informationUri": "https://github.com/google/osv-scanner",
+          "name": "osv-scanner",
+          "rules": [
+            {
+              "id": "CVE-2022-24713",
+              "shortDescription": {
+                "text": "CVE-2022-24713: <advisory summary>"
+              },
+              "fullDescription": {
+                "text": "<Full advisory details>...",
+                "markdown": "<Full advisory details>..."
+              },
+              // Deprecated IDs field contains all alias IDs
+              "deprecatedIds": [
+                "CVE-2022-24713",
+                "RUSTSEC-2022-0013",
+                "GHSA-m5pq-gvj9-9vr8"
+              ],
+              "help": {
+                "text": "<Markdown help text>...",
+                "markdown": "<Markdown help text>..."
+              }
+            },
+          ],
+          "version": "1.4.1"
+        }
+      },
+      "artifacts": [
+        {
+          "location": {
+            "uri": "file:///path/to/sub-rust-project/Cargo.lock"
+          },
+          "length": -1
+        }
+      ],
+      "results": [
+        {
+          "ruleId": "CVE-2022-24713",
+          "ruleIndex": 0,
+          "level": "warning",
+          "message": {
+            "text": "Package 'regex@1.5.1' is vulnerable to 'CVE-2022-24713' (also known as 'RUSTSEC-2022-0013', 'GHSA-m5pq-gvj9-9vr8')."
+          },
+          "locations": [
+            {
+              "physicalLocation": {
+                "artifactLocation": {
+                  "uri": "file:///path/to/sub-rust-project/Cargo.lock"
+                }
+              }
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
+```
+
+</details>
+
+<details markdown="1">
+<summary><b>Sample SARIF Help Text</b></summary>
+
+
+> **Your dependency is vulnerable to [CVE-2022-24713](https://osv.dev/list?q=CVE-2022-24713)**
+> (Also published as:  [RUSTSEC-2022-0013](https://osv.dev/vulnerability/RUSTSEC-2022-0013),  [GHSA-m5pq-gvj9-9vr8](https://osv.dev/vulnerability/GHSA-m5pq-gvj9-9vr8), ).
+>
+> {:.no_toc}
+> ## [RUSTSEC-2022-0013](https://osv.dev/vulnerability/RUSTSEC-2022-0013)
+>
+> <details>
+> <summary>Details</summary>
+>
+> > Full advisory details...
+>
+> </details>
+>
+>
+> {:.no_toc}
+> ## [GHSA-m5pq-gvj9-9vr8](https://osv.dev/vulnerability/GHSA-m5pq-gvj9-9vr8)
+>
+> <details>
+> <summary>Details</summary>
+>
+> > Full advisory details...
+>
+> </details>
+>
+>
+> ---
+>
+> {:.no_toc}
+> ### Affected Packages
+>
+> | Source | Package Name | Package Version |
+> | --- | --- | --- |
+> | lockfile:/path/to/rust-project/Cargo.lock | regex | 1.5.1 |
+>
+> {:.no_toc}
+> ## Remediation
+>
+>
+>
+> To fix these vulnerabilities, update the vulnerabilities past the listed fixed versions below.
+>
+> {:.no_toc}
+> ### Fixed Versions
+>
+> | Vulnerability ID | Package Name | Fixed Version |
+> | --- | --- | --- |
+> | GHSA-m5pq-gvj9-9vr8 | regex | 1.5.5 |
+> | RUSTSEC-2022-0013 | regex | 1.5.5 |
+>
+>
+> If you believe these vulnerabilities do not affect your code and wish to ignore them, add them to the ignore list in an
+> `osv-scanner.toml` file located in the same directory as the lockfile containing the vulnerable dependency.
+>
+> See the format and more options in our documentation here: https://google.github.io/osv-scanner/configuration/
+>
+> Add or append these values to the following config files to ignore this vulnerability:
+>
+>
+> `/path/to/rust-project/osv-scanner.toml`
+> ```
+> [[IgnoredVulns]]
+> id = "CVE-2022-24713"
+> reason = "Your reason for ignoring this vulnerability"
+> ```
+
+</details>
+
+---
+
 ## Call analysis
 
 With `--experimental-call-analysis` flag enabled, call information will be included in the output.
@@ -367,12 +522,12 @@ osv-scanner --format json --experimental-call-analysis -L path/to/lockfile > /pa
 
 ## Return Codes
 
-|----- 
-| Exit Code |Reason| 
-|:---------------:|------------| 
-| `0` | Packages were found when scanning, but does not match any known vulnerabilities. | 
-| `1` | Packages were found when scanning, and there are vulnerabilities. | 
-| `1-126` | Reserved for vulnerability result related errors. | 
-| `127` | General Error. | 
-| `128` | No packages found (likely caused by the scanning format not picking up any files to scan). | 
-| `129-255` | Reserved for non result related errors. | 
+|-----
+| Exit Code |Reason|
+|:---------------:|------------|
+| `0` | Packages were found when scanning, but does not match any known vulnerabilities. |
+| `1` | Packages were found when scanning, and there are vulnerabilities. |
+| `1-126` | Reserved for vulnerability result related errors. |
+| `127` | General Error. |
+| `128` | No packages found (likely caused by the scanning format not picking up any files to scan). |
+| `129-255` | Reserved for non result related errors. |
diff --git a/docs/usage.md b/docs/usage.md
index 15612fa..e907cc2 100644
--- a/docs/usage.md
+++ b/docs/usage.md
@@ -25,9 +25,9 @@ osv-scanner -r /path/to/your/dir
 
 The preceding command will find lockfiles, SBOMs, and git directories in your target directory and use them to determine the dependencies to check against the OSV database for any known vulnerabilities.
 
-The recursive flag `-r` or `--recursive` will tell the scanner to search all subdirectories in addition to the specified directory. It can find additional lockfiles, dependencies, and vulnerabilities. If your project has deeply nested subdirectories, a recursive search may take a long time. 
+The recursive flag `-r` or `--recursive` will tell the scanner to search all subdirectories in addition to the specified directory. It can find additional lockfiles, dependencies, and vulnerabilities. If your project has deeply nested subdirectories, a recursive search may take a long time.
 
-Git directories are searched for the latest commit hash. Searching for git commit hash is intended to work with projects that use git submodules or a similar mechanism where dependencies are checked out as real git repositories. 
+Git directories are searched for the latest commit hash. Searching for git commit hash is intended to work with projects that use git submodules or a similar mechanism where dependencies are checked out as real git repositories.
 
 ## Ignored files
 
@@ -110,7 +110,7 @@ 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. 
+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.:
 
@@ -121,6 +121,7 @@ Once you extracted your own dependency information, place it in a `osv-scanner.j
       "packages": [
         {
           "package": {
+            "name": "github.com/repo/url",
             "commit": "9a6bd55c9d0722cb101fe85a3b22d89e4ff4fe52"
           }
         },
@@ -145,7 +146,7 @@ osv-scanner --lockfile osv-scanner:/path/to/osv-scanner.json
 
 ## Scanning a Debian based docker image packages
 Preview
-{: .label } 
+{: .label }
 
 This tool will scrape the list of installed packages in a Debian image and query for vulnerabilities on them.
 
@@ -180,4 +181,12 @@ appropriate osv-scanner flags:
 
 ```bash
 docker run -it -v ${PWD}:/src ghcr.io/google/osv-scanner -L /src/go.mod
-```
\ No newline at end of file
+```
+
+## Saving to file
+
+The `--output` flag can be used to save the scan results to a file instead of being printed on the stdout:
+
+```bash
+osv-scanner -L package-lock.json --output scan-results.txt
+```
diff --git a/go.mod b/go.mod
index 521c05b..121b022 100644
--- a/go.mod
+++ b/go.mod
@@ -8,18 +8,18 @@ require (
 	github.com/go-git/go-billy/v5 v5.5.0
 	github.com/go-git/go-git/v5 v5.9.0
 	github.com/goark/go-cvss v1.6.6
-	github.com/google/go-cmp v0.5.9
+	github.com/google/go-cmp v0.6.0
 	github.com/hexops/gotextdiff v1.0.3
-	github.com/jedib0t/go-pretty/v6 v6.4.7
+	github.com/jedib0t/go-pretty/v6 v6.4.8
 	github.com/kr/pretty v0.3.1
-	github.com/owenrumney/go-sarif/v2 v2.2.2
-	github.com/package-url/packageurl-go v0.1.1
+	github.com/owenrumney/go-sarif/v2 v2.3.0
+	github.com/package-url/packageurl-go v0.1.2
 	github.com/spdx/tools-golang v0.5.3
 	github.com/urfave/cli/v2 v2.25.7
-	golang.org/x/exp v0.0.0-20230905200255-921286631fa9
-	golang.org/x/mod v0.12.0
-	golang.org/x/sync v0.3.0
-	golang.org/x/term v0.12.0
+	golang.org/x/exp v0.0.0-20231006140011-7918f672742d
+	golang.org/x/mod v0.13.0
+	golang.org/x/sync v0.4.0
+	golang.org/x/term v0.13.0
 	golang.org/x/vuln v1.0.1
 	gopkg.in/yaml.v3 v3.0.1
 )
@@ -52,9 +52,9 @@ require (
 	github.com/spdx/gordf v0.0.0-20221230105357-b735bd5aac89 // indirect
 	github.com/xanzy/ssh-agent v0.3.3 // indirect
 	github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
-	golang.org/x/crypto v0.13.0 // indirect
-	golang.org/x/net v0.15.0 // indirect
-	golang.org/x/sys v0.12.0 // indirect
-	golang.org/x/tools v0.13.0 // indirect
+	golang.org/x/crypto v0.14.0 // indirect
+	golang.org/x/net v0.17.0 // indirect
+	golang.org/x/sys v0.13.0 // indirect
+	golang.org/x/tools v0.14.0 // indirect
 	gopkg.in/warnings.v0 v0.1.2 // indirect
 )
diff --git a/go.sum b/go.sum
index 7bbc3d8..87a4d52 100644
--- a/go.sum
+++ b/go.sum
@@ -7,13 +7,10 @@ github.com/CycloneDX/cyclonedx-go v0.7.2/go.mod h1:K2bA+324+Og0X84fA8HhN2X066K7B
 github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
 github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
 github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
-github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg=
-github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
 github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c h1:kMFnB0vCcX7IL/m9Y5LO+KQYv+t1CQOiFe6+SV2J7bE=
 github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
 github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ=
 github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
-github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 h1:aM1rlcoLz8y5B2r4tTLMiVTrMtpfY0O8EScKJxaSaEc=
 github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA=
 github.com/anchore/go-struct-converter v0.0.0-20230627203149-c72ef8859ca9 h1:6COpXWpHbhWM1wgcQN95TdsmrLTba8KQfPgImBXzkjA=
 github.com/anchore/go-struct-converter v0.0.0-20230627203149-c72ef8859ca9/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA=
@@ -43,8 +40,6 @@ github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgF
 github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f h1:Pz0DHeFij3XFhoBRGUDPzSJ+w2UcK5/0JvF8DRI58r8=
 github.com/go-git/go-git/v5 v5.9.0 h1:cD9SFA7sHVRdJ7AYck1ZaAa/yeuBvGPxwXDL8cxrObY=
 github.com/go-git/go-git/v5 v5.9.0/go.mod h1:RKIqga24sWdMGZF+1Ekv9kylsDz6LzdTSI2s/OsZWE0=
-github.com/goark/errs v1.1.0 h1:FKnyw4LVyRADIjM8Nj0Up6r0/y5cfADvZAd1E+tthXE=
-github.com/goark/errs v1.1.0/go.mod h1:TtaPEoadm2mzqzfXdkkfpN2xuniCFm2q4JH+c1qzaqw=
 github.com/goark/errs v1.3.2 h1:ifccNe1aK7Xezt4XVYwHUqalmnfhuphnEvh3FshCReQ=
 github.com/goark/errs v1.3.2/go.mod h1:ZsQucxaDFVfSB8I99j4bxkDRfNOrlKINwg72QMuRWKw=
 github.com/goark/go-cvss v1.6.6 h1:WJFuIWqmAw1Ilb9USv0vuX+nYzOWJp8lIujseJ/y3sU=
@@ -54,16 +49,17 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4er
 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
 github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
 github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
 github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
 github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab h1:BA4a7pe6ZTd9F8kXETBoijjFJ/ntaa//1wiH9BZu4zU=
 github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
-github.com/jedib0t/go-pretty/v6 v6.4.7 h1:lwiTJr1DEkAgzljsUsORmWsVn5MQjt1BPJdPCtJ6KXE=
-github.com/jedib0t/go-pretty/v6 v6.4.7/go.mod h1:Ndk3ase2CkQbXLLNf5QDHoYb6J9WtVfmHZu9n8rk2xs=
+github.com/jedib0t/go-pretty/v6 v6.4.8 h1:HiNzyMSEpsBaduKhmK+CwcpulEeBrTmxutz4oX/oWkg=
+github.com/jedib0t/go-pretty/v6 v6.4.8/go.mod h1:Ndk3ase2CkQbXLLNf5QDHoYb6J9WtVfmHZu9n8rk2xs=
 github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
 github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -75,17 +71,15 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
 github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
-github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
 github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
 github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
 github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
 github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
-github.com/owenrumney/go-sarif v1.1.1 h1:QNObu6YX1igyFKhdzd7vgzmw7XsWN3/6NMGuDzBgXmE=
 github.com/owenrumney/go-sarif v1.1.1/go.mod h1:dNDiPlF04ESR/6fHlPyq7gHKmrM0sHUvAGjsoh8ZH0U=
-github.com/owenrumney/go-sarif/v2 v2.2.2 h1:x2acaiiAW9hu+78wbEYBRGLk5nRtHmkv7HeUsKvblwc=
-github.com/owenrumney/go-sarif/v2 v2.2.2/go.mod h1:MSqMMx9WqlBSY7pXoOZWgEsVB4FDNfhcaXDA1j6Sr+w=
-github.com/package-url/packageurl-go v0.1.1 h1:KTRE0bK3sKbFKAk3yy63DpeskU7Cvs/x/Da5l+RtzyU=
-github.com/package-url/packageurl-go v0.1.1/go.mod h1:uQd4a7Rh3ZsVg5j0lNyAfyxIeGde9yrlhjF78GzeW0c=
+github.com/owenrumney/go-sarif/v2 v2.3.0 h1:wP5yEpI53zr0v5cBmagXzLbHZp9Oylyo3AJDpfLBITs=
+github.com/owenrumney/go-sarif/v2 v2.3.0/go.mod h1:MSqMMx9WqlBSY7pXoOZWgEsVB4FDNfhcaXDA1j6Sr+w=
+github.com/package-url/packageurl-go v0.1.2 h1:0H2DQt6DHd/NeRlVwW4EZ4oEI6Bn40XlNPRqegcxuo4=
+github.com/package-url/packageurl-go v0.1.2/go.mod h1:uQd4a7Rh3ZsVg5j0lNyAfyxIeGde9yrlhjF78GzeW0c=
 github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
 github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
 github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
@@ -94,7 +88,6 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
 github.com/pkg/profile v1.6.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
 github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
 github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
 github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
@@ -103,13 +96,9 @@ github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDN
 github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
 github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
-github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
 github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
 github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
 github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
-github.com/skeema/knownhosts v1.2.0 h1:h9r9cf0+u7wSE+M183ZtMGgOJKiL96brpaz5ekfJCpM=
-github.com/skeema/knownhosts v1.2.0/go.mod h1:g4fPeYpque7P0xefxtGzV81ihjC8sX2IqpAoNkjxbMo=
 github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ=
 github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
 github.com/spdx/gordf v0.0.0-20201111095634-7098f93598fb/go.mod h1:uKWaldnbMnjsSAXRurWqqrdyZen1R7kxl8TkmWk2OyM=
@@ -147,14 +136,14 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
 golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
-golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
-golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
-golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
-golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
+golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
+golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
+golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
+golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
-golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
+golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
 golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -164,13 +153,13 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
 golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
 golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
-golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
-golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
+golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
+golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
-golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
+golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -185,15 +174,15 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
-golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
+golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
 golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
-golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU=
-golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
+golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
+golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -208,10 +197,8 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
-golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
-golang.org/x/vuln v1.0.0 h1:tYLAU3jD9LQr98Y+3el06lWyGMCnvzw06PIWP3LIy7g=
-golang.org/x/vuln v1.0.0/go.mod h1:V0eyhHwaAaHrt42J9bgrN6rd12f6GU4T0Lu0ex2wDg4=
+golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
+golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
 golang.org/x/vuln v1.0.1 h1:KUas02EjQK5LTuIx1OylBQdKKZ9jeugs+HiqO5HormU=
 golang.org/x/vuln v1.0.1/go.mod h1:bb2hMwln/tqxg32BNY4CcxHWtHXuYa3SbIBmtsyjxtM=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -223,7 +210,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
 gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
 gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
diff --git a/internal/output/fixtures/commit-grouped.json b/internal/output/fixtures/commit-grouped.json
new file mode 100644
index 0000000..3960b8f
--- /dev/null
+++ b/internal/output/fixtures/commit-grouped.json
@@ -0,0 +1,129 @@
+{
+  "DisplayID": "OSV-2023-72",
+  "PkgSource": [
+    {
+      "Package": {
+        "name": "https://fuchsia.googlesource.com/third_party/android.googlesource.com/platform/external/perfetto",
+        "version": "",
+        "ecosystem": "",
+        "commit": "b8da07095979310818f0efde2ef3c69ea70d62c5"
+      },
+      "Source": {
+        "path": "/usr/local/google/home/rexpan/Documents/Project/engine/deps_flatten.txt",
+        "type": "lockfile"
+      }
+    }
+  ],
+  "AliasedVulns": {
+    "OSV-2023-72": {
+      "modified": "2023-04-20T22:43:30Z",
+      "published": "2023-02-18T13:00:15Z",
+      "schema_version": "1.6.0",
+      "id": "OSV-2023-72",
+      "summary": "Heap-buffer-overflow in perfetto::trace_processor::TrackEventParser::ParseTrackDescriptor",
+      "details": "OSS-Fuzz report: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=56057\n\n```\nCrash type: Heap-buffer-overflow WRITE 4\nCrash state:\nperfetto::trace_processor::TrackEventParser::ParseTrackDescriptor\nperfetto::trace_processor::TrackEventModule::ParseTracePacketData\nperfetto::trace_processor::ProtoTraceParser::ParseTracePacket\n```\n",
+      "affected": [
+        {
+          "package": {
+            "ecosystem": "OSS-Fuzz",
+            "name": "perfetto",
+            "purl": "pkg:generic/perfetto"
+          },
+          "ranges": [
+            {
+              "type": "GIT",
+              "events": [
+                {
+                  "introduced": "8209fb9b9a4156232aa87ad4621e541bfb777ec1"
+                },
+                {
+                  "fixed": "9a7f09383dd39f19e662d428321ca708a2a600a3"
+                }
+              ],
+              "repo": "https://android.googlesource.com/platform/external/perfetto/"
+            }
+          ],
+          "versions": [
+            "android-13.0.0_r1",
+            "android-13.0.0_r12",
+            "android-13.0.0_r2",
+            "android-13.0.0_r3",
+            "android-13.0.0_r31",
+            "android-13.0.0_r4",
+            "android-13.0.0_r5",
+            "android-13.0.0_r6",
+            "android-13.0.0_r7",
+            "android-13.0.0_r8",
+            "android-cts-13.0_r1",
+            "android-cts-13.0_r2",
+            "android-cts-13.0_r3",
+            "android-mainline-12.0.0_r100",
+            "android-mainline-12.0.0_r122",
+            "android-mainline-12.0.0_r49",
+            "android-mainline-12.0.0_r59",
+            "android-mainline-12.0.0_r63",
+            "android-mainline-12.0.0_r70",
+            "android-mainline-12.0.0_r77",
+            "android-mainline-12.0.0_r99",
+            "android-platform-13.0.0_r1",
+            "android-platform-13.0.0_r2",
+            "android-security-13.0.0_r1",
+            "android-security-13.0.0_r2",
+            "android-vts-13.0_r1",
+            "android-vts-13.0_r2",
+            "android-vts-13.0_r3",
+            "platform-tools-29.0.1",
+            "platform-tools-29.0.2",
+            "platform-tools-29.0.3",
+            "platform-tools-29.0.4",
+            "platform-tools-29.0.5",
+            "platform-tools-29.0.6",
+            "platform-tools-30.0.0",
+            "platform-tools-30.0.1",
+            "platform-tools-30.0.2",
+            "platform-tools-30.0.3",
+            "platform-tools-30.0.4",
+            "platform-tools-30.0.5",
+            "platform-tools-31.0.0",
+            "platform-tools-31.0.1",
+            "platform-tools-31.0.2",
+            "platform-tools-31.0.3",
+            "platform-tools-32.0.0",
+            "platform-tools-33.0.0",
+            "platform-tools-33.0.1",
+            "platform-tools-33.0.2",
+            "platform-tools-33.0.3",
+            "platform-tools-33.0.4",
+            "platform-tools-34.0.0",
+            "v27.0",
+            "v27.1",
+            "v28.0",
+            "v29.0",
+            "v30.0",
+            "v31.0",
+            "v32.0",
+            "v32.1",
+            "v32.2",
+            "android-security-13.0.0_r3",
+            "android-security-13.0.0_r4"
+          ],
+          "database_specific": {
+            "source": "https://github.com/google/oss-fuzz-vulns/blob/main/vulns/perfetto/OSV-2023-72.yaml"
+          },
+          "ecosystem_specific": {
+            "severity": "HIGH"
+          }
+        }
+      ],
+      "references": [
+        {
+          "type": "REPORT",
+          "url": "https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=56057"
+        }
+      ]
+    }
+  },
+  "AliasedIDList": [
+    "OSV-2023-72"
+  ]
+}
diff --git a/internal/output/fixtures/sarif-commit-output.md b/internal/output/fixtures/sarif-commit-output.md
new file mode 100644
index 0000000..550ef1e
--- /dev/null
+++ b/internal/output/fixtures/sarif-commit-output.md
@@ -0,0 +1,61 @@
+
+**Your dependency is vulnerable to [OSV-2023-72](https://osv.dev/list?q=OSV-2023-72)**.
+
+
+## [OSV-2023-72](https://osv.dev/vulnerability/OSV-2023-72)
+
+<details>
+<summary>Details</summary>
+
+> OSS-Fuzz report: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=56057
+> 
+> ```
+> Crash type: Heap-buffer-overflow WRITE 4
+> Crash state:
+> perfetto::trace_processor::TrackEventParser::ParseTrackDescriptor
+> perfetto::trace_processor::TrackEventModule::ParseTracePacketData
+> perfetto::trace_processor::ProtoTraceParser::ParseTracePacket
+> ```
+> 
+
+</details>
+
+
+
+---
+
+### Affected Packages
+
+| Source | Package Name | Package Version |
+| --- | --- | --- |
+| lockfile:/usr/local/google/home/rexpan/Documents/Project/engine/deps_flatten.txt | https://fuchsia.googlesource.com/third_party/android.googlesource.com/platform/external/perfetto | b8da07095979310818f0efde2ef3c69ea70d62c5 |
+
+## Remediation
+
+
+
+To fix these vulnerabilities, update the vulnerabilities past the listed fixed versions below.
+
+### Fixed Versions
+
+| Vulnerability ID | Package Name | Fixed Version |
+| --- | --- | --- |
+| OSV-2023-72 | perfetto | 9a7f09383dd39f19e662d428321ca708a2a600a3 |
+
+
+
+If you believe these vulnerabilities do not affect your code and wish to ignore them, add them to the ignore list in an
+`osv-scanner.toml` file located in the same directory as the lockfile containing the vulnerable dependency.
+
+See the format and more options in our documentation here: https://google.github.io/osv-scanner/configuration/
+
+Add or append these values to the following config files to ignore this vulnerability:
+
+
+`/usr/local/google/home/rexpan/Documents/Project/engine/osv-scanner.toml`
+```
+[[IgnoredVulns]]
+id = "OSV-2023-72"
+reason = "Your reason for ignoring this vulnerability"
+```
+
diff --git a/internal/output/fixtures/sarif-output.md b/internal/output/fixtures/sarif-output.md
index 3043493..08fe8b8 100644
--- a/internal/output/fixtures/sarif-output.md
+++ b/internal/output/fixtures/sarif-output.md
@@ -104,6 +104,7 @@
 ---
 
 ### Affected Packages
+
 | Source | Package Name | Package Version |
 | --- | --- | --- |
 | lockfile:/path/to/sub-rust-project/Cargo.lock | regex | 1.5.1 |
@@ -115,12 +116,14 @@
 To fix these vulnerabilities, update the vulnerabilities past the listed fixed versions below.
 
 ### Fixed Versions
+
 | Vulnerability ID | Package Name | Fixed Version |
 | --- | --- | --- |
 | GHSA-m5pq-gvj9-9vr8 | regex | 1.5.5 |
 | RUSTSEC-2022-0013 | regex | 1.5.5 |
 
 
+
 If you believe these vulnerabilities do not affect your code and wish to ignore them, add them to the ignore list in an
 `osv-scanner.toml` file located in the same directory as the lockfile containing the vulnerable dependency.
 
diff --git a/internal/output/sarif.go b/internal/output/sarif.go
index 5ff47a9..f46ec54 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/utility/results"
 	"github.com/google/osv-scanner/internal/version"
 	"github.com/google/osv-scanner/pkg/models"
 	"github.com/jedib0t/go-pretty/v6/table"
@@ -57,6 +58,7 @@ const SARIFTemplate = `
 ---
 
 ### Affected Packages
+
 {{.AffectedPackagesTable}}
 
 ## Remediation
@@ -66,7 +68,9 @@ const SARIFTemplate = `
 To fix these vulnerabilities, update the vulnerabilities past the listed fixed versions below.
 
 ### Fixed Versions
+
 {{.FixedVersionTable}}
+
 {{end}}
 
 If you believe these vulnerabilities do not affect your code and wish to ignore them, add them to the ignore list in an
@@ -120,10 +124,14 @@ func createSARIFAffectedPkgTable(pkgWithSrc []pkgWithSource) table.Writer {
 	helpTable.AppendHeader(table.Row{"Source", "Package Name", "Package Version"})
 
 	for _, ps := range pkgWithSrc {
+		version := ps.Package.Version
+		if ps.Package.Commit != "" {
+			version = ps.Package.Commit
+		}
 		helpTable.AppendRow(table.Row{
 			ps.Source.String(),
 			ps.Package.Name,
-			ps.Package.Version,
+			version,
 		})
 	}
 
@@ -259,6 +267,12 @@ func PrintSARIFReport(vulnResult *models.VulnerabilityResults, outputWriter io.W
 			}
 		}
 
+		// If no advisory for this vulnerability has a summary field,
+		// just show the ID in the shortDescription
+		if shortDescription == "" {
+			shortDescription = gv.DisplayID
+		}
+
 		rule := run.AddRule(gv.DisplayID).
 			WithShortDescription(sarif.NewMultiformatMessageString(shortDescription)).
 			WithFullDescription(sarif.NewMultiformatMessageString(longDescription).WithMarkdown(longDescription)).
@@ -285,9 +299,8 @@ func PrintSARIFReport(vulnResult *models.VulnerabilityResults, outputWriter io.W
 				WithMessage(
 					sarif.NewTextMessage(
 						fmt.Sprintf(
-							"Package '%s@%s' is vulnerable to '%s'%s.",
-							pws.Package.Name,
-							pws.Package.Version,
+							"Package '%s' is vulnerable to '%s'%s.",
+							results.PkgToString(pws.Package),
 							gv.DisplayID,
 							alsoKnownAsStr,
 						))).
diff --git a/internal/output/table.go b/internal/output/table.go
index 3eb7523..6976772 100644
--- a/internal/output/table.go
+++ b/internal/output/table.go
@@ -12,6 +12,7 @@ import (
 	v2_metric "github.com/goark/go-cvss/v2/metric"
 	v3_metric "github.com/goark/go-cvss/v3/metric"
 
+	"github.com/google/osv-scanner/internal/utility/results"
 	"github.com/google/osv-scanner/pkg/models"
 
 	"github.com/jedib0t/go-pretty/v6/table"
@@ -109,7 +110,8 @@ func tableBuilderInner(vulnResult *models.VulnerabilityResults, addStyling bool,
 				outputRow = append(outputRow, MaxSeverity(group, pkg))
 
 				if pkg.Package.Ecosystem == "" && pkg.Package.Commit != "" {
-					outputRow = append(outputRow, "GIT", pkg.Package.Commit, pkg.Package.Commit)
+					pkgCommitStr := results.PkgToString(pkg.Package)
+					outputRow = append(outputRow, "GIT", pkgCommitStr, pkgCommitStr)
 					shouldMerge = true
 				} else {
 					outputRow = append(outputRow, pkg.Package.Ecosystem, pkg.Package.Name, pkg.Package.Version)
diff --git a/internal/utility/results/results.go b/internal/utility/results/results.go
new file mode 100644
index 0000000..131be97
--- /dev/null
+++ b/internal/utility/results/results.go
@@ -0,0 +1,24 @@
+package results
+
+import (
+	"fmt"
+
+	"github.com/google/osv-scanner/pkg/models"
+)
+
+// Number of characters to display a git commit
+const ShortCommitLen = 8
+
+func PkgToString(pkgInfo models.PackageInfo) string {
+	if pkgInfo.Commit != "" {
+		if pkgInfo.Name != "" {
+			// https://github.com/google/osv-scanner@12345678
+			return fmt.Sprint(pkgInfo.Name, "@", pkgInfo.Commit[:ShortCommitLen])
+		}
+		// 1234567890abcdefghij1234567890abcdefghij
+		return pkgInfo.Commit
+	}
+
+	// abc@v1.2.3
+	return fmt.Sprint(pkgInfo.Name, "@", pkgInfo.Version)
+}
diff --git a/pkg/lockfile/fixtures/yarn/with-build-string.v1.lock b/pkg/lockfile/fixtures/yarn/with-build-string.v1.lock
new file mode 100644
index 0000000..b95d949
--- /dev/null
+++ b/pkg/lockfile/fixtures/yarn/with-build-string.v1.lock
@@ -0,0 +1,13 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"domino@https://github.com/angular/domino.git#f2435fe1f9f7c91ade0bd472c4723e5eacd7d19a":
+  version "2.1.6+git"
+  resolved "git+ssh://git@github.com/angular/domino.git"
+  integrity sha512-1D4hj4hN9Q3Coi+gXZjFlxrm+7Jkhe/WBWU6loAQ/BqDWDRYwqQB1YkKbCVvfaVJXAB8OM2sae7KMyqM69pfRQ==
+
+tslib@^2.3.0:
+  version "2.6.2"
+  resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz"
+  integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
diff --git a/pkg/lockfile/fixtures/yarn/with-build-string.v2.lock b/pkg/lockfile/fixtures/yarn/with-build-string.v2.lock
new file mode 100644
index 0000000..de6dd4e
--- /dev/null
+++ b/pkg/lockfile/fixtures/yarn/with-build-string.v2.lock
@@ -0,0 +1,29 @@
+# This file is generated by running "yarn install" inside your project.
+# Manual changes might be lost - proceed with caution!
+
+__metadata:
+  version: 6
+  cacheKey: 8
+
+"domino@https://github.com/angular/domino.git#f2435fe1f9f7c91ade0bd472c4723e5eacd7d19a":
+  version: 2.1.6+git
+  resolution: "domino@https://github.com/angular/domino.git#commit=f2435fe1f9f7c91ade0bd472c4723e5eacd7d19a"
+  checksum: 0d9cacf8fd9ee104b9608dd1bb309520db40026e9b31533f3de5994a779bddbf0865820b67bc735c7dcb8067497c35835eb14c1656c31e0679d250f1cfd41073
+  languageName: node
+  linkType: hard
+
+"tslib@npm:^2.3.0":
+  version: 2.6.2
+  resolution: "tslib@npm:2.6.2"
+  checksum: 329ea56123005922f39642318e3d1f0f8265d1e7fcb92c633e0809521da75eeaca28d2cf96d7248229deb40e5c19adf408259f4b9640afd20d13aecc1430f3ad
+  languageName: node
+  linkType: hard
+
+"zone.js@workspace:.":
+  version: 0.0.0-use.local
+  resolution: "zone.js@workspace:."
+  dependencies:
+    domino: "https://github.com/angular/domino.git#f2435fe1f9f7c91ade0bd472c4723e5eacd7d19a"
+    tslib: ^2.3.0
+  languageName: unknown
+  linkType: soft
diff --git a/pkg/lockfile/fixtures/yarn/versions-with-build-strings.v1.lock b/pkg/lockfile/fixtures/yarn/with-prerelease.v1.lock
similarity index 100%
rename from pkg/lockfile/fixtures/yarn/versions-with-build-strings.v1.lock
rename to pkg/lockfile/fixtures/yarn/with-prerelease.v1.lock
diff --git a/pkg/lockfile/fixtures/yarn/versions-with-build-strings.v2.lock b/pkg/lockfile/fixtures/yarn/with-prerelease.v2.lock
similarity index 100%
rename from pkg/lockfile/fixtures/yarn/versions-with-build-strings.v2.lock
rename to pkg/lockfile/fixtures/yarn/with-prerelease.v2.lock
diff --git a/pkg/lockfile/osv-vuln-results.go b/pkg/lockfile/osv-vuln-results.go
index 2f2cf48..c1e1ed1 100644
--- a/pkg/lockfile/osv-vuln-results.go
+++ b/pkg/lockfile/osv-vuln-results.go
@@ -32,6 +32,7 @@ func (e OSVScannerResultsExtractor) Extract(f DepFile) ([]PackageDetails, error)
 			if pkg.Package.Commit != "" { // Prioritize results
 				packages = append(packages, PackageDetails{
 					Commit: pkg.Package.Commit,
+					Name:   pkg.Package.Name,
 				})
 			} else {
 				packages = append(packages, PackageDetails{
diff --git a/pkg/lockfile/parse-yarn-lock.go b/pkg/lockfile/parse-yarn-lock.go
index 5c764c7..43e6836 100644
--- a/pkg/lockfile/parse-yarn-lock.go
+++ b/pkg/lockfile/parse-yarn-lock.go
@@ -65,7 +65,7 @@ func extractYarnPackageName(str string) string {
 }
 
 func determineYarnPackageVersion(group []string) string {
-	re := cachedregexp.MustCompile(`^ {2}"?version"?:? "?([\w-.]+)"?$`)
+	re := cachedregexp.MustCompile(`^ {2}"?version"?:? "?([\w-.+]+)"?$`)
 
 	for _, s := range group {
 		matched := re.FindStringSubmatch(s)
diff --git a/pkg/models/results.go b/pkg/models/results.go
index 2ed4cc1..02d9f2e 100644
--- a/pkg/models/results.go
+++ b/pkg/models/results.go
@@ -49,6 +49,10 @@ type SourceInfo struct {
 	Type string `json:"type"`
 }
 
+type Metadata struct {
+	RepoURL string `json:"repo_url"`
+}
+
 func (s SourceInfo) String() string {
 	return s.Type + ":" + s.Path
 }
diff --git a/pkg/osv/osv.go b/pkg/osv/osv.go
index 6cb95af..3d9a13b 100644
--- a/pkg/osv/osv.go
+++ b/pkg/osv/osv.go
@@ -39,10 +39,11 @@ type Package struct {
 
 // Query represents a query to OSV.
 type Query struct {
-	Commit  string            `json:"commit,omitempty"`
-	Package Package           `json:"package,omitempty"`
-	Version string            `json:"version,omitempty"`
-	Source  models.SourceInfo `json:"-"`
+	Commit   string            `json:"commit,omitempty"`
+	Package  Package           `json:"package,omitempty"`
+	Version  string            `json:"version,omitempty"`
+	Source   models.SourceInfo `json:"-"` // TODO: Move this into Info struct in v2
+	Metadata models.Metadata   `json:"-"`
 }
 
 // BatchedQuery represents a batched query to OSV.
@@ -95,6 +96,9 @@ func MakePkgRequest(pkgDetails lockfile.PackageDetails) *Query {
 	// API has trouble parsing requests with both commit and Package details filled in
 	if pkgDetails.Ecosystem == "" && pkgDetails.Commit != "" {
 		return &Query{
+			Metadata: models.Metadata{
+				RepoURL: pkgDetails.Name,
+			},
 			Commit: pkgDetails.Commit,
 		}
 	} else {
diff --git a/pkg/osvscanner/osvscanner.go b/pkg/osvscanner/osvscanner.go
index 6bb9e0f..3f18e86 100644
--- a/pkg/osvscanner/osvscanner.go
+++ b/pkg/osvscanner/osvscanner.go
@@ -589,7 +589,7 @@ func DoScan(actions ScannerActions, r reporter.Reporter) (models.VulnerabilityRe
 		return models.VulnerabilityResults{}, err
 	}
 
-	vulnerabilityResults := groupResponseBySource(r, query, hydratedResp, actions.CallAnalysis)
+	vulnerabilityResults := buildVulnerabilityResults(r, query, hydratedResp, actions.CallAnalysis)
 
 	filtered := filterResults(r, &vulnerabilityResults, &configManager)
 	if filtered > 0 {
diff --git a/pkg/osvscanner/vulnerability_result.go b/pkg/osvscanner/vulnerability_result.go
index 7ad57fc..64170f0 100644
--- a/pkg/osvscanner/vulnerability_result.go
+++ b/pkg/osvscanner/vulnerability_result.go
@@ -11,9 +11,9 @@ import (
 	"github.com/google/osv-scanner/pkg/reporter"
 )
 
-// groupResponseBySource converts raw OSV API response into structured vulnerability information
+// buildVulnerabilityResults converts raw OSV API response into structured vulnerability information
 // grouped by source location.
-func groupResponseBySource(r reporter.Reporter, query osv.BatchedQuery, resp *osv.HydratedBatchedResponse, callAnalysis bool) models.VulnerabilityResults {
+func buildVulnerabilityResults(r reporter.Reporter, query osv.BatchedQuery, resp *osv.HydratedBatchedResponse, callAnalysis bool) models.VulnerabilityResults {
 	output := models.VulnerabilityResults{
 		Results: []models.PackageSource{},
 	}
@@ -27,6 +27,7 @@ func groupResponseBySource(r reporter.Reporter, query osv.BatchedQuery, resp *os
 		var pkg models.PackageVulns
 		if query.Commit != "" {
 			pkg.Package.Commit = query.Commit
+			pkg.Package.Name = query.Metadata.RepoURL
 		} else if query.Package.PURL != "" {
 			var err error
 			pkg.Package, err = models.PURLToPackage(query.Package.PURL)


Test patch:
diff --git a/cmd/osv-scanner/main_test.go b/cmd/osv-scanner/main_test.go
index 8fefc49..9505318 100644
--- a/cmd/osv-scanner/main_test.go
+++ b/cmd/osv-scanner/main_test.go
@@ -189,6 +189,7 @@ func TestRun(t *testing.T) {
 				+-------------------------------------+------+-----------+--------------------------------+------------------------------------+-------------------------------------------------+
 				| OSV URL                             | CVSS | ECOSYSTEM | PACKAGE                        | VERSION                            | SOURCE                                          |
 				+-------------------------------------+------+-----------+--------------------------------+------------------------------------+-------------------------------------------------+
+				| https://osv.dev/CVE-2022-48174      | 9.8  | Alpine    | busybox                        | 1.35.0-r29                         | fixtures/sbom-insecure/alpine.cdx.xml           |
 				| https://osv.dev/CVE-2022-37434      | 9.8  | Alpine    | zlib                           | 1.2.10-r2                          | fixtures/sbom-insecure/alpine.cdx.xml           |
 				| https://osv.dev/DLA-3022-1          |      | Debian    | dpkg                           | 1.18.25                            | fixtures/sbom-insecure/postgres-stretch.cdx.xml |
 				| https://osv.dev/GHSA-v95c-p5hm-xq8f | 6    | Go        | github.com/opencontainers/runc | v1.0.1                             | fixtures/sbom-insecure/postgres-stretch.cdx.xml |
@@ -212,12 +213,13 @@ func TestRun(t *testing.T) {
 			args:         []string{"", "--config=./fixtures/osv-scanner-empty-config.toml", "--sbom", "./fixtures/sbom-insecure/alpine.cdx.xml"},
 			wantExitCode: 1,
 			wantStdout: `
-      	Scanned <rootdir>/fixtures/sbom-insecure/alpine.cdx.xml as CycloneDX SBOM and found 15 packages
-      	+--------------------------------+------+-----------+---------+-----------+---------------------------------------+
-      	| OSV URL                        | CVSS | ECOSYSTEM | PACKAGE | VERSION   | SOURCE                                |
-      	+--------------------------------+------+-----------+---------+-----------+---------------------------------------+
-      	| https://osv.dev/CVE-2022-37434 | 9.8  | Alpine    | zlib    | 1.2.10-r2 | fixtures/sbom-insecure/alpine.cdx.xml |
-      	+--------------------------------+------+-----------+---------+-----------+---------------------------------------+
+				Scanned <rootdir>/fixtures/sbom-insecure/alpine.cdx.xml as CycloneDX SBOM and found 15 packages
+				+--------------------------------+------+-----------+---------+------------+---------------------------------------+
+				| OSV URL                        | CVSS | ECOSYSTEM | PACKAGE | VERSION    | SOURCE                                |
+				+--------------------------------+------+-----------+---------+------------+---------------------------------------+
+				| https://osv.dev/CVE-2022-48174 | 9.8  | Alpine    | busybox | 1.35.0-r29 | fixtures/sbom-insecure/alpine.cdx.xml |
+				| https://osv.dev/CVE-2022-37434 | 9.8  | Alpine    | zlib    | 1.2.10-r2  | fixtures/sbom-insecure/alpine.cdx.xml |
+				+--------------------------------+------+-----------+---------+------------+---------------------------------------+
 			`,
 			wantStderr: "",
 		},
@@ -246,8 +248,9 @@ func TestRun(t *testing.T) {
 				Scanned <rootdir>/fixtures/locks-many/package-lock.json file and found 1 package
 				Scanned <rootdir>/fixtures/locks-many/yarn.lock file and found 1 package
 				Loaded filter from: <rootdir>/fixtures/locks-many/osv-scanner.toml
+				CVE-2022-48174 has been filtered out because: Test manifest file (alpine.cdx.xml)
 				GHSA-whgm-jr23-g3j9 has been filtered out because: Test manifest file
-				Filtered 1 vulnerability from output
+				Filtered 2 vulnerabilities from output
 				No vulnerabilities found
 			`,
 			wantStderr: "",
@@ -360,7 +363,7 @@ func TestRun(t *testing.T) {
 			wantStdout: fmt.Sprintf(`
             {
               "version": "2.1.0",
-              "$schema": "https://json.schemastore.org/sarif-2.1.0.json",
+              "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
               "runs": [
                 {
                   "tool": {
@@ -388,7 +391,7 @@ func TestRun(t *testing.T) {
 			wantStdout: fmt.Sprint(`
 						{
               "version": "2.1.0",
-              "$schema": "https://json.schemastore.org/sarif-2.1.0.json",
+              "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
               "runs": [
                 {
                   "tool": {
@@ -707,6 +710,141 @@ func TestRun_LockfileWithExplicitParseAs(t *testing.T) {
 	}
 }
 
+// TestRun_GithubActions tests common actions the github actions reusable workflow will run
+func TestRun_GithubActions(t *testing.T) {
+	t.Parallel()
+
+	tests := []cliTestCase{
+		{
+			name:         "scanning osv-scanner custom format",
+			args:         []string{"", "-L", "osv-scanner:./fixtures/locks-insecure/osv-scanner-flutter-deps.json"},
+			wantExitCode: 1,
+			wantStdout: `
+				Scanned <rootdir>/fixtures/locks-insecure/osv-scanner-flutter-deps.json file as a osv-scanner and found 3 packages
+				+--------------------------------+------+-----------+----------------------------+----------------------------+-------------------------------------------------------+
+				| OSV URL                        | CVSS | ECOSYSTEM | PACKAGE                    | VERSION                    | SOURCE                                                |
+				+--------------------------------+------+-----------+----------------------------+----------------------------+-------------------------------------------------------+
+				| https://osv.dev/CVE-2023-39137 | 7.8  | GIT       |  https://github.com/brendan-duncan/archive.git@9de7a054 | fixtures/locks-insecure/osv-scanner-flutter-deps.json |
+				| https://osv.dev/CVE-2023-39139 | 7.8  | GIT       |  https://github.com/brendan-duncan/archive.git@9de7a054 | fixtures/locks-insecure/osv-scanner-flutter-deps.json |
+				+--------------------------------+------+-----------+---------------------------------------------------------+-------------------------------------------------------+
+`,
+			wantStderr: "",
+		},
+		{
+			name:         "scanning osv-scanner custom format output json",
+			args:         []string{"", "-L", "osv-scanner:./fixtures/locks-insecure/osv-scanner-flutter-deps.json", "--format=sarif"},
+			wantExitCode: 1,
+			wantStdout: `
+        {
+          "version": "2.1.0",
+          "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
+          "runs": [
+            {
+              "tool": {
+                "driver": {
+                  "informationUri": "https://github.com/google/osv-scanner",
+                  "name": "osv-scanner",
+                  "rules": [
+                    {
+                      "id": "CVE-2023-39137",
+                      "shortDescription": {
+                        "text": "CVE-2023-39137"
+                      },
+                      "fullDescription": {
+                        "text": "An issue in Archive v3.3.7 allows attackers to spoof zip filenames which can lead to inconsistent filename parsing.",
+                        "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"
+                      ],
+                      "help": {
+                        "text": "%%",
+                        "markdown": "%%"
+                      }
+                    },
+                    {
+                      "id": "CVE-2023-39139",
+                      "shortDescription": {
+                        "text": "CVE-2023-39139"
+                      },
+                      "fullDescription": {
+                        "text": "An issue in Archive v3.3.7 allows attackers to execute a path traversal via extracting a crafted zip file.",
+                        "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"
+                      ],
+                      "help": {
+                        "text": "%%",
+                        "markdown": "%%"
+                      }
+                    }
+                  ],
+                  "version": "1.4.1"
+                }
+              },
+              "artifacts": [
+                {
+                  "location": {
+                    "uri": "file://<rootdir>/fixtures/locks-insecure/osv-scanner-flutter-deps.json"
+                  },
+                  "length": -1
+                }
+              ],
+              "results": [
+                {
+                  "ruleId": "CVE-2023-39137",
+                  "ruleIndex": 0,
+                  "level": "warning",
+                  "message": {
+                    "text": "Package 'https://github.com/brendan-duncan/archive.git@9de7a054' is vulnerable to 'CVE-2023-39137'."
+                  },
+                  "locations": [
+                    {
+                      "physicalLocation": {
+                        "artifactLocation": {
+                          "uri": "file://<rootdir>/fixtures/locks-insecure/osv-scanner-flutter-deps.json"
+                        }
+                      }
+                    }
+                  ]
+                },
+                {
+                  "ruleId": "CVE-2023-39139",
+                  "ruleIndex": 1,
+                  "level": "warning",
+                  "message": {
+                    "text": "Package 'https://github.com/brendan-duncan/archive.git@9de7a054' is vulnerable to 'CVE-2023-39139'."
+                  },
+                  "locations": [
+                    {
+                      "physicalLocation": {
+                        "artifactLocation": {
+                          "uri": "file://<rootdir>/fixtures/locks-insecure/osv-scanner-flutter-deps.json"
+                        }
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          ]
+        }`,
+			wantStderr: `
+				Scanned <rootdir>/fixtures/locks-insecure/osv-scanner-flutter-deps.json file as a osv-scanner and found 3 packages
+			`,
+		},
+	}
+	for _, tt := range tests {
+		tt := tt
+		t.Run(tt.name, func(t *testing.T) {
+			t.Parallel()
+
+			testCli(t, tt)
+		})
+	}
+}
+
 func TestRun_LocalDatabases(t *testing.T) {
 	t.Parallel()
 
diff --git a/internal/output/fixtures/test-vuln-results-a.sarif b/internal/output/fixtures/test-vuln-results-a.sarif
index ea1ca9f..a3f92f3 100644
--- a/internal/output/fixtures/test-vuln-results-a.sarif
+++ b/internal/output/fixtures/test-vuln-results-a.sarif
@@ -1,6 +1,6 @@
 {
   "version": "2.1.0",
-  "$schema": "https://json.schemastore.org/sarif-2.1.0.json",
+  "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
   "runs": [
     {
       "tool": {
@@ -23,8 +23,8 @@
                 "GHSA-m5pq-gvj9-9vr8"
               ],
               "help": {
-                "text": "\n**Your dependency is vulnerable to [CVE-2022-24713](https://osv.dev/list?q=CVE-2022-24713)**\n(Also published as:  [RUSTSEC-2022-0013](https://osv.dev/vulnerability/RUSTSEC-2022-0013),  [GHSA-m5pq-gvj9-9vr8](https://osv.dev/vulnerability/GHSA-m5pq-gvj9-9vr8), ).\n\n\n## [RUSTSEC-2022-0013](https://osv.dev/vulnerability/RUSTSEC-2022-0013)\n\n\u003cdetails\u003e\n\u003csummary\u003eDetails\u003c/summary\u003e\n\n\u003e The Rust Security Response WG was notified that the `regex` crate did not\n\u003e properly limit the complexity of the regular expressions (regex) it parses. An\n\u003e attacker could use this security issue to perform a denial of service, by\n\u003e sending a specially crafted regex to a service accepting untrusted regexes. No\n\u003e known vulnerability is present when parsing untrusted input with trusted\n\u003e regexes.\n\u003e \n\u003e This issue has been assigned CVE-2022-24713. The severity of this vulnerability\n\u003e is \"high\" when the `regex` crate is used to parse untrusted regexes. Other uses\n\u003e of the `regex` crate are not affected by this vulnerability.\n\u003e \n\u003e ## Overview\n\u003e \n\u003e The `regex` crate features built-in mitigations to prevent denial of service\n\u003e attacks caused by untrusted regexes, or untrusted input matched by trusted\n\u003e regexes. Those (tunable) mitigations already provide sane defaults to prevent\n\u003e attacks. This guarantee is documented and it's considered part of the crate's\n\u003e API.\n\u003e \n\u003e Unfortunately a bug was discovered in the mitigations designed to prevent\n\u003e untrusted regexes to take an arbitrary amount of time during parsing, and it's\n\u003e possible to craft regexes that bypass such mitigations. This makes it possible\n\u003e to perform denial of service attacks by sending specially crafted regexes to\n\u003e services accepting user-controlled, untrusted regexes.\n\u003e \n\u003e ## Affected versions\n\u003e \n\u003e All versions of the `regex` crate before or equal to 1.5.4 are affected by this\n\u003e issue. The fix is include starting from  `regex` 1.5.5.\n\u003e \n\u003e ## Mitigations\n\u003e \n\u003e We recommend everyone accepting user-controlled regexes to upgrade immediately\n\u003e to the latest version of the `regex` crate.\n\u003e \n\u003e Unfortunately there is no fixed set of problematic regexes, as there are\n\u003e practically infinite regexes that could be crafted to exploit this\n\u003e vulnerability. Because of this, we do not recommend denying known problematic\n\u003e regexes.\n\u003e \n\u003e ## Acknowledgements\n\u003e \n\u003e We want to thank Addison Crump for responsibly disclosing this to us according\n\u003e to the [Rust security policy][1], and for helping review the fix.\n\u003e \n\u003e We also want to thank Andrew Gallant for developing the fix, and Pietro Albini\n\u003e for coordinating the disclosure and writing this advisory.\n\u003e \n\u003e [1]: https://www.rust-lang.org/policies/security\n\n\u003c/details\u003e\n\n\n\n## [GHSA-m5pq-gvj9-9vr8](https://osv.dev/vulnerability/GHSA-m5pq-gvj9-9vr8)\n\n\u003cdetails\u003e\n\u003csummary\u003eDetails\u003c/summary\u003e\n\n\u003e \u003e This is a cross-post of [the official security advisory][advisory]. The official advisory contains a signed version with our PGP key, as well.\n\u003e \n\u003e [advisory]: https://groups.google.com/g/rustlang-security-announcements/c/NcNNL1Jq7Yw\n\u003e \n\u003e The Rust Security Response WG was notified that the `regex` crate did not properly limit the complexity of the regular expressions (regex) it parses. An attacker could use this security issue to perform a denial of service, by sending a specially crafted regex to a service accepting untrusted regexes. No known vulnerability is present when parsing untrusted input with trusted regexes.\n\u003e \n\u003e This issue has been assigned CVE-2022-24713. The severity of this vulnerability is \"high\" when the `regex` crate is used to parse untrusted regexes. Other uses of the `regex` crate are not affected by this vulnerability.\n\u003e \n\u003e ## Overview\n\u003e \n\u003e The `regex` crate features built-in mitigations to prevent denial of service attacks caused by untrusted regexes, or untrusted input matched by trusted regexes. Those (tunable) mitigations already provide sane defaults to prevent attacks. This guarantee is documented and it's considered part of the crate's API.\n\u003e \n\u003e Unfortunately a bug was discovered in the mitigations designed to prevent untrusted regexes to take an arbitrary amount of time during parsing, and it's possible to craft regexes that bypass such mitigations. This makes it possible to perform denial of service attacks by sending specially crafted regexes to services accepting user-controlled, untrusted regexes.\n\u003e \n\u003e ## Affected versions\n\u003e \n\u003e All versions of the `regex` crate before or equal to 1.5.4 are affected by this issue. The fix is include starting from  `regex` 1.5.5.\n\u003e \n\u003e ## Mitigations\n\u003e \n\u003e We recommend everyone accepting user-controlled regexes to upgrade immediately to the latest version of the `regex` crate.\n\u003e \n\u003e Unfortunately there is no fixed set of problematic regexes, as there are practically infinite regexes that could be crafted to exploit this vulnerability. Because of this, we do not recommend denying known problematic regexes.\n\u003e \n\u003e ## Acknowledgements\n\u003e \n\u003e We want to thank Addison Crump for responsibly disclosing this to us according to the [Rust security policy](https://www.rust-lang.org/policies/security), and for helping review the fix.\n\u003e \n\u003e We also want to thank Andrew Gallant for developing the fix, and Pietro Albini for coordinating the disclosure and writing this advisory.\n\n\u003c/details\u003e\n\n\n\n---\n\n### Affected Packages\n| Source | Package Name | Package Version |\n| --- | --- | --- |\n| lockfile:/path/to/sub-rust-project/Cargo.lock | regex | 1.5.1 |\n\n## Remediation\n\n\n\nTo fix these vulnerabilities, update the vulnerabilities past the listed fixed versions below.\n\n### Fixed Versions\n| Vulnerability ID | Package Name | Fixed Version |\n| --- | --- | --- |\n| GHSA-m5pq-gvj9-9vr8 | regex | 1.5.5 |\n| RUSTSEC-2022-0013 | regex | 1.5.5 |\n\n\nIf you believe these vulnerabilities do not affect your code and wish to ignore them, add them to the ignore list in an\n`osv-scanner.toml` file located in the same directory as the lockfile containing the vulnerable dependency.\n\nSee the format and more options in our documentation here: https://google.github.io/osv-scanner/configuration/\n\nAdd or append these values to the following config files to ignore this vulnerability:\n\n\n`/path/to/sub-rust-project/osv-scanner.toml`\n```\n[[IgnoredVulns]]\nid = \"CVE-2022-24713\"\nreason = \"Your reason for ignoring this vulnerability\"\n```\n\n",
-                "markdown": "\n**Your dependency is vulnerable to [CVE-2022-24713](https://osv.dev/list?q=CVE-2022-24713)**\n(Also published as:  [RUSTSEC-2022-0013](https://osv.dev/vulnerability/RUSTSEC-2022-0013),  [GHSA-m5pq-gvj9-9vr8](https://osv.dev/vulnerability/GHSA-m5pq-gvj9-9vr8), ).\n\n\n## [RUSTSEC-2022-0013](https://osv.dev/vulnerability/RUSTSEC-2022-0013)\n\n\u003cdetails\u003e\n\u003csummary\u003eDetails\u003c/summary\u003e\n\n\u003e The Rust Security Response WG was notified that the `regex` crate did not\n\u003e properly limit the complexity of the regular expressions (regex) it parses. An\n\u003e attacker could use this security issue to perform a denial of service, by\n\u003e sending a specially crafted regex to a service accepting untrusted regexes. No\n\u003e known vulnerability is present when parsing untrusted input with trusted\n\u003e regexes.\n\u003e \n\u003e This issue has been assigned CVE-2022-24713. The severity of this vulnerability\n\u003e is \"high\" when the `regex` crate is used to parse untrusted regexes. Other uses\n\u003e of the `regex` crate are not affected by this vulnerability.\n\u003e \n\u003e ## Overview\n\u003e \n\u003e The `regex` crate features built-in mitigations to prevent denial of service\n\u003e attacks caused by untrusted regexes, or untrusted input matched by trusted\n\u003e regexes. Those (tunable) mitigations already provide sane defaults to prevent\n\u003e attacks. This guarantee is documented and it's considered part of the crate's\n\u003e API.\n\u003e \n\u003e Unfortunately a bug was discovered in the mitigations designed to prevent\n\u003e untrusted regexes to take an arbitrary amount of time during parsing, and it's\n\u003e possible to craft regexes that bypass such mitigations. This makes it possible\n\u003e to perform denial of service attacks by sending specially crafted regexes to\n\u003e services accepting user-controlled, untrusted regexes.\n\u003e \n\u003e ## Affected versions\n\u003e \n\u003e All versions of the `regex` crate before or equal to 1.5.4 are affected by this\n\u003e issue. The fix is include starting from  `regex` 1.5.5.\n\u003e \n\u003e ## Mitigations\n\u003e \n\u003e We recommend everyone accepting user-controlled regexes to upgrade immediately\n\u003e to the latest version of the `regex` crate.\n\u003e \n\u003e Unfortunately there is no fixed set of problematic regexes, as there are\n\u003e practically infinite regexes that could be crafted to exploit this\n\u003e vulnerability. Because of this, we do not recommend denying known problematic\n\u003e regexes.\n\u003e \n\u003e ## Acknowledgements\n\u003e \n\u003e We want to thank Addison Crump for responsibly disclosing this to us according\n\u003e to the [Rust security policy][1], and for helping review the fix.\n\u003e \n\u003e We also want to thank Andrew Gallant for developing the fix, and Pietro Albini\n\u003e for coordinating the disclosure and writing this advisory.\n\u003e \n\u003e [1]: https://www.rust-lang.org/policies/security\n\n\u003c/details\u003e\n\n\n\n## [GHSA-m5pq-gvj9-9vr8](https://osv.dev/vulnerability/GHSA-m5pq-gvj9-9vr8)\n\n\u003cdetails\u003e\n\u003csummary\u003eDetails\u003c/summary\u003e\n\n\u003e \u003e This is a cross-post of [the official security advisory][advisory]. The official advisory contains a signed version with our PGP key, as well.\n\u003e \n\u003e [advisory]: https://groups.google.com/g/rustlang-security-announcements/c/NcNNL1Jq7Yw\n\u003e \n\u003e The Rust Security Response WG was notified that the `regex` crate did not properly limit the complexity of the regular expressions (regex) it parses. An attacker could use this security issue to perform a denial of service, by sending a specially crafted regex to a service accepting untrusted regexes. No known vulnerability is present when parsing untrusted input with trusted regexes.\n\u003e \n\u003e This issue has been assigned CVE-2022-24713. The severity of this vulnerability is \"high\" when the `regex` crate is used to parse untrusted regexes. Other uses of the `regex` crate are not affected by this vulnerability.\n\u003e \n\u003e ## Overview\n\u003e \n\u003e The `regex` crate features built-in mitigations to prevent denial of service attacks caused by untrusted regexes, or untrusted input matched by trusted regexes. Those (tunable) mitigations already provide sane defaults to prevent attacks. This guarantee is documented and it's considered part of the crate's API.\n\u003e \n\u003e Unfortunately a bug was discovered in the mitigations designed to prevent untrusted regexes to take an arbitrary amount of time during parsing, and it's possible to craft regexes that bypass such mitigations. This makes it possible to perform denial of service attacks by sending specially crafted regexes to services accepting user-controlled, untrusted regexes.\n\u003e \n\u003e ## Affected versions\n\u003e \n\u003e All versions of the `regex` crate before or equal to 1.5.4 are affected by this issue. The fix is include starting from  `regex` 1.5.5.\n\u003e \n\u003e ## Mitigations\n\u003e \n\u003e We recommend everyone accepting user-controlled regexes to upgrade immediately to the latest version of the `regex` crate.\n\u003e \n\u003e Unfortunately there is no fixed set of problematic regexes, as there are practically infinite regexes that could be crafted to exploit this vulnerability. Because of this, we do not recommend denying known problematic regexes.\n\u003e \n\u003e ## Acknowledgements\n\u003e \n\u003e We want to thank Addison Crump for responsibly disclosing this to us according to the [Rust security policy](https://www.rust-lang.org/policies/security), and for helping review the fix.\n\u003e \n\u003e We also want to thank Andrew Gallant for developing the fix, and Pietro Albini for coordinating the disclosure and writing this advisory.\n\n\u003c/details\u003e\n\n\n\n---\n\n### Affected Packages\n| Source | Package Name | Package Version |\n| --- | --- | --- |\n| lockfile:/path/to/sub-rust-project/Cargo.lock | regex | 1.5.1 |\n\n## Remediation\n\n\n\nTo fix these vulnerabilities, update the vulnerabilities past the listed fixed versions below.\n\n### Fixed Versions\n| Vulnerability ID | Package Name | Fixed Version |\n| --- | --- | --- |\n| GHSA-m5pq-gvj9-9vr8 | regex | 1.5.5 |\n| RUSTSEC-2022-0013 | regex | 1.5.5 |\n\n\nIf you believe these vulnerabilities do not affect your code and wish to ignore them, add them to the ignore list in an\n`osv-scanner.toml` file located in the same directory as the lockfile containing the vulnerable dependency.\n\nSee the format and more options in our documentation here: https://google.github.io/osv-scanner/configuration/\n\nAdd or append these values to the following config files to ignore this vulnerability:\n\n\n`/path/to/sub-rust-project/osv-scanner.toml`\n```\n[[IgnoredVulns]]\nid = \"CVE-2022-24713\"\nreason = \"Your reason for ignoring this vulnerability\"\n```\n\n"
+                "text": "\n**Your dependency is vulnerable to [CVE-2022-24713](https://osv.dev/list?q=CVE-2022-24713)**\n(Also published as:  [RUSTSEC-2022-0013](https://osv.dev/vulnerability/RUSTSEC-2022-0013),  [GHSA-m5pq-gvj9-9vr8](https://osv.dev/vulnerability/GHSA-m5pq-gvj9-9vr8), ).\n\n\n## [RUSTSEC-2022-0013](https://osv.dev/vulnerability/RUSTSEC-2022-0013)\n\n\u003cdetails\u003e\n\u003csummary\u003eDetails\u003c/summary\u003e\n\n\u003e The Rust Security Response WG was notified that the `regex` crate did not\n\u003e properly limit the complexity of the regular expressions (regex) it parses. An\n\u003e attacker could use this security issue to perform a denial of service, by\n\u003e sending a specially crafted regex to a service accepting untrusted regexes. No\n\u003e known vulnerability is present when parsing untrusted input with trusted\n\u003e regexes.\n\u003e \n\u003e This issue has been assigned CVE-2022-24713. The severity of this vulnerability\n\u003e is \"high\" when the `regex` crate is used to parse untrusted regexes. Other uses\n\u003e of the `regex` crate are not affected by this vulnerability.\n\u003e \n\u003e ## Overview\n\u003e \n\u003e The `regex` crate features built-in mitigations to prevent denial of service\n\u003e attacks caused by untrusted regexes, or untrusted input matched by trusted\n\u003e regexes. Those (tunable) mitigations already provide sane defaults to prevent\n\u003e attacks. This guarantee is documented and it's considered part of the crate's\n\u003e API.\n\u003e \n\u003e Unfortunately a bug was discovered in the mitigations designed to prevent\n\u003e untrusted regexes to take an arbitrary amount of time during parsing, and it's\n\u003e possible to craft regexes that bypass such mitigations. This makes it possible\n\u003e to perform denial of service attacks by sending specially crafted regexes to\n\u003e services accepting user-controlled, untrusted regexes.\n\u003e \n\u003e ## Affected versions\n\u003e \n\u003e All versions of the `regex` crate before or equal to 1.5.4 are affected by this\n\u003e issue. The fix is include starting from  `regex` 1.5.5.\n\u003e \n\u003e ## Mitigations\n\u003e \n\u003e We recommend everyone accepting user-controlled regexes to upgrade immediately\n\u003e to the latest version of the `regex` crate.\n\u003e \n\u003e Unfortunately there is no fixed set of problematic regexes, as there are\n\u003e practically infinite regexes that could be crafted to exploit this\n\u003e vulnerability. Because of this, we do not recommend denying known problematic\n\u003e regexes.\n\u003e \n\u003e ## Acknowledgements\n\u003e \n\u003e We want to thank Addison Crump for responsibly disclosing this to us according\n\u003e to the [Rust security policy][1], and for helping review the fix.\n\u003e \n\u003e We also want to thank Andrew Gallant for developing the fix, and Pietro Albini\n\u003e for coordinating the disclosure and writing this advisory.\n\u003e \n\u003e [1]: https://www.rust-lang.org/policies/security\n\n\u003c/details\u003e\n\n\n\n## [GHSA-m5pq-gvj9-9vr8](https://osv.dev/vulnerability/GHSA-m5pq-gvj9-9vr8)\n\n\u003cdetails\u003e\n\u003csummary\u003eDetails\u003c/summary\u003e\n\n\u003e \u003e This is a cross-post of [the official security advisory][advisory]. The official advisory contains a signed version with our PGP key, as well.\n\u003e \n\u003e [advisory]: https://groups.google.com/g/rustlang-security-announcements/c/NcNNL1Jq7Yw\n\u003e \n\u003e The Rust Security Response WG was notified that the `regex` crate did not properly limit the complexity of the regular expressions (regex) it parses. An attacker could use this security issue to perform a denial of service, by sending a specially crafted regex to a service accepting untrusted regexes. No known vulnerability is present when parsing untrusted input with trusted regexes.\n\u003e \n\u003e This issue has been assigned CVE-2022-24713. The severity of this vulnerability is \"high\" when the `regex` crate is used to parse untrusted regexes. Other uses of the `regex` crate are not affected by this vulnerability.\n\u003e \n\u003e ## Overview\n\u003e \n\u003e The `regex` crate features built-in mitigations to prevent denial of service attacks caused by untrusted regexes, or untrusted input matched by trusted regexes. Those (tunable) mitigations already provide sane defaults to prevent attacks. This guarantee is documented and it's considered part of the crate's API.\n\u003e \n\u003e Unfortunately a bug was discovered in the mitigations designed to prevent untrusted regexes to take an arbitrary amount of time during parsing, and it's possible to craft regexes that bypass such mitigations. This makes it possible to perform denial of service attacks by sending specially crafted regexes to services accepting user-controlled, untrusted regexes.\n\u003e \n\u003e ## Affected versions\n\u003e \n\u003e All versions of the `regex` crate before or equal to 1.5.4 are affected by this issue. The fix is include starting from  `regex` 1.5.5.\n\u003e \n\u003e ## Mitigations\n\u003e \n\u003e We recommend everyone accepting user-controlled regexes to upgrade immediately to the latest version of the `regex` crate.\n\u003e \n\u003e Unfortunately there is no fixed set of problematic regexes, as there are practically infinite regexes that could be crafted to exploit this vulnerability. Because of this, we do not recommend denying known problematic regexes.\n\u003e \n\u003e ## Acknowledgements\n\u003e \n\u003e We want to thank Addison Crump for responsibly disclosing this to us according to the [Rust security policy](https://www.rust-lang.org/policies/security), and for helping review the fix.\n\u003e \n\u003e We also want to thank Andrew Gallant for developing the fix, and Pietro Albini for coordinating the disclosure and writing this advisory.\n\n\u003c/details\u003e\n\n\n\n---\n\n### Affected Packages\n\n| Source | Package Name | Package Version |\n| --- | --- | --- |\n| lockfile:/path/to/sub-rust-project/Cargo.lock | regex | 1.5.1 |\n\n## Remediation\n\n\n\nTo fix these vulnerabilities, update the vulnerabilities past the listed fixed versions below.\n\n### Fixed Versions\n\n| Vulnerability ID | Package Name | Fixed Version |\n| --- | --- | --- |\n| GHSA-m5pq-gvj9-9vr8 | regex | 1.5.5 |\n| RUSTSEC-2022-0013 | regex | 1.5.5 |\n\n\n\nIf you believe these vulnerabilities do not affect your code and wish to ignore them, add them to the ignore list in an\n`osv-scanner.toml` file located in the same directory as the lockfile containing the vulnerable dependency.\n\nSee the format and more options in our documentation here: https://google.github.io/osv-scanner/configuration/\n\nAdd or append these values to the following config files to ignore this vulnerability:\n\n\n`/path/to/sub-rust-project/osv-scanner.toml`\n```\n[[IgnoredVulns]]\nid = \"CVE-2022-24713\"\nreason = \"Your reason for ignoring this vulnerability\"\n```\n\n",
+                "markdown": "\n**Your dependency is vulnerable to [CVE-2022-24713](https://osv.dev/list?q=CVE-2022-24713)**\n(Also published as:  [RUSTSEC-2022-0013](https://osv.dev/vulnerability/RUSTSEC-2022-0013),  [GHSA-m5pq-gvj9-9vr8](https://osv.dev/vulnerability/GHSA-m5pq-gvj9-9vr8), ).\n\n\n## [RUSTSEC-2022-0013](https://osv.dev/vulnerability/RUSTSEC-2022-0013)\n\n\u003cdetails\u003e\n\u003csummary\u003eDetails\u003c/summary\u003e\n\n\u003e The Rust Security Response WG was notified that the `regex` crate did not\n\u003e properly limit the complexity of the regular expressions (regex) it parses. An\n\u003e attacker could use this security issue to perform a denial of service, by\n\u003e sending a specially crafted regex to a service accepting untrusted regexes. No\n\u003e known vulnerability is present when parsing untrusted input with trusted\n\u003e regexes.\n\u003e \n\u003e This issue has been assigned CVE-2022-24713. The severity of this vulnerability\n\u003e is \"high\" when the `regex` crate is used to parse untrusted regexes. Other uses\n\u003e of the `regex` crate are not affected by this vulnerability.\n\u003e \n\u003e ## Overview\n\u003e \n\u003e The `regex` crate features built-in mitigations to prevent denial of service\n\u003e attacks caused by untrusted regexes, or untrusted input matched by trusted\n\u003e regexes. Those (tunable) mitigations already provide sane defaults to prevent\n\u003e attacks. This guarantee is documented and it's considered part of the crate's\n\u003e API.\n\u003e \n\u003e Unfortunately a bug was discovered in the mitigations designed to prevent\n\u003e untrusted regexes to take an arbitrary amount of time during parsing, and it's\n\u003e possible to craft regexes that bypass such mitigations. This makes it possible\n\u003e to perform denial of service attacks by sending specially crafted regexes to\n\u003e services accepting user-controlled, untrusted regexes.\n\u003e \n\u003e ## Affected versions\n\u003e \n\u003e All versions of the `regex` crate before or equal to 1.5.4 are affected by this\n\u003e issue. The fix is include starting from  `regex` 1.5.5.\n\u003e \n\u003e ## Mitigations\n\u003e \n\u003e We recommend everyone accepting user-controlled regexes to upgrade immediately\n\u003e to the latest version of the `regex` crate.\n\u003e \n\u003e Unfortunately there is no fixed set of problematic regexes, as there are\n\u003e practically infinite regexes that could be crafted to exploit this\n\u003e vulnerability. Because of this, we do not recommend denying known problematic\n\u003e regexes.\n\u003e \n\u003e ## Acknowledgements\n\u003e \n\u003e We want to thank Addison Crump for responsibly disclosing this to us according\n\u003e to the [Rust security policy][1], and for helping review the fix.\n\u003e \n\u003e We also want to thank Andrew Gallant for developing the fix, and Pietro Albini\n\u003e for coordinating the disclosure and writing this advisory.\n\u003e \n\u003e [1]: https://www.rust-lang.org/policies/security\n\n\u003c/details\u003e\n\n\n\n## [GHSA-m5pq-gvj9-9vr8](https://osv.dev/vulnerability/GHSA-m5pq-gvj9-9vr8)\n\n\u003cdetails\u003e\n\u003csummary\u003eDetails\u003c/summary\u003e\n\n\u003e \u003e This is a cross-post of [the official security advisory][advisory]. The official advisory contains a signed version with our PGP key, as well.\n\u003e \n\u003e [advisory]: https://groups.google.com/g/rustlang-security-announcements/c/NcNNL1Jq7Yw\n\u003e \n\u003e The Rust Security Response WG was notified that the `regex` crate did not properly limit the complexity of the regular expressions (regex) it parses. An attacker could use this security issue to perform a denial of service, by sending a specially crafted regex to a service accepting untrusted regexes. No known vulnerability is present when parsing untrusted input with trusted regexes.\n\u003e \n\u003e This issue has been assigned CVE-2022-24713. The severity of this vulnerability is \"high\" when the `regex` crate is used to parse untrusted regexes. Other uses of the `regex` crate are not affected by this vulnerability.\n\u003e \n\u003e ## Overview\n\u003e \n\u003e The `regex` crate features built-in mitigations to prevent denial of service attacks caused by untrusted regexes, or untrusted input matched by trusted regexes. Those (tunable) mitigations already provide sane defaults to prevent attacks. This guarantee is documented and it's considered part of the crate's API.\n\u003e \n\u003e Unfortunately a bug was discovered in the mitigations designed to prevent untrusted regexes to take an arbitrary amount of time during parsing, and it's possible to craft regexes that bypass such mitigations. This makes it possible to perform denial of service attacks by sending specially crafted regexes to services accepting user-controlled, untrusted regexes.\n\u003e \n\u003e ## Affected versions\n\u003e \n\u003e All versions of the `regex` crate before or equal to 1.5.4 are affected by this issue. The fix is include starting from  `regex` 1.5.5.\n\u003e \n\u003e ## Mitigations\n\u003e \n\u003e We recommend everyone accepting user-controlled regexes to upgrade immediately to the latest version of the `regex` crate.\n\u003e \n\u003e Unfortunately there is no fixed set of problematic regexes, as there are practically infinite regexes that could be crafted to exploit this vulnerability. Because of this, we do not recommend denying known problematic regexes.\n\u003e \n\u003e ## Acknowledgements\n\u003e \n\u003e We want to thank Addison Crump for responsibly disclosing this to us according to the [Rust security policy](https://www.rust-lang.org/policies/security), and for helping review the fix.\n\u003e \n\u003e We also want to thank Andrew Gallant for developing the fix, and Pietro Albini for coordinating the disclosure and writing this advisory.\n\n\u003c/details\u003e\n\n\n\n---\n\n### Affected Packages\n\n| Source | Package Name | Package Version |\n| --- | --- | --- |\n| lockfile:/path/to/sub-rust-project/Cargo.lock | regex | 1.5.1 |\n\n## Remediation\n\n\n\nTo fix these vulnerabilities, update the vulnerabilities past the listed fixed versions below.\n\n### Fixed Versions\n\n| Vulnerability ID | Package Name | Fixed Version |\n| --- | --- | --- |\n| GHSA-m5pq-gvj9-9vr8 | regex | 1.5.5 |\n| RUSTSEC-2022-0013 | regex | 1.5.5 |\n\n\n\nIf you believe these vulnerabilities do not affect your code and wish to ignore them, add them to the ignore list in an\n`osv-scanner.toml` file located in the same directory as the lockfile containing the vulnerable dependency.\n\nSee the format and more options in our documentation here: https://google.github.io/osv-scanner/configuration/\n\nAdd or append these values to the following config files to ignore this vulnerability:\n\n\n`/path/to/sub-rust-project/osv-scanner.toml`\n```\n[[IgnoredVulns]]\nid = \"CVE-2022-24713\"\nreason = \"Your reason for ignoring this vulnerability\"\n```\n\n"
               }
             },
             {
@@ -42,12 +42,12 @@
                 "GHSA-c3h9-896r-86jm"
               ],
               "help": {
-                "text": "\n**Your dependency is vulnerable to [CVE-2021-3121](https://osv.dev/list?q=CVE-2021-3121)**.\n\n\n## [GO-2021-0053](https://osv.dev/vulnerability/GO-2021-0053)\n\n\u003cdetails\u003e\n\u003csummary\u003eDetails\u003c/summary\u003e\n\n\u003e Due to improper bounds checking, maliciously crafted input to generated Unmarshal methods can cause an out-of-bounds panic. If parsing messages from untrusted parties, this may be used as a denial of service vector.\n\n\u003c/details\u003e\n\n\n\n---\n\n### Affected Packages\n| Source | Package Name | Package Version |\n| --- | --- | --- |\n| lockfile:/path/to/go.mod | github.com/gogo/protobuf | 1.3.1 |\n\n## Remediation\n\n\n\nTo fix these vulnerabilities, update the vulnerabilities past the listed fixed versions below.\n\n### Fixed Versions\n| Vulnerability ID | Package Name | Fixed Version |\n| --- | --- | --- |\n| GO-2021-0053 | github.com/gogo/protobuf | 1.3.2 |\n\n\nIf you believe these vulnerabilities do not affect your code and wish to ignore them, add them to the ignore list in an\n`osv-scanner.toml` file located in the same directory as the lockfile containing the vulnerable dependency.\n\nSee the format and more options in our documentation here: https://google.github.io/osv-scanner/configuration/\n\nAdd or append these values to the following config files to ignore this vulnerability:\n\n\n`/path/to/osv-scanner.toml`\n```\n[[IgnoredVulns]]\nid = \"CVE-2021-3121\"\nreason = \"Your reason for ignoring this vulnerability\"\n```\n\n",
-                "markdown": "\n**Your dependency is vulnerable to [CVE-2021-3121](https://osv.dev/list?q=CVE-2021-3121)**.\n\n\n## [GO-2021-0053](https://osv.dev/vulnerability/GO-2021-0053)\n\n\u003cdetails\u003e\n\u003csummary\u003eDetails\u003c/summary\u003e\n\n\u003e Due to improper bounds checking, maliciously crafted input to generated Unmarshal methods can cause an out-of-bounds panic. If parsing messages from untrusted parties, this may be used as a denial of service vector.\n\n\u003c/details\u003e\n\n\n\n---\n\n### Affected Packages\n| Source | Package Name | Package Version |\n| --- | --- | --- |\n| lockfile:/path/to/go.mod | github.com/gogo/protobuf | 1.3.1 |\n\n## Remediation\n\n\n\nTo fix these vulnerabilities, update the vulnerabilities past the listed fixed versions below.\n\n### Fixed Versions\n| Vulnerability ID | Package Name | Fixed Version |\n| --- | --- | --- |\n| GO-2021-0053 | github.com/gogo/protobuf | 1.3.2 |\n\n\nIf you believe these vulnerabilities do not affect your code and wish to ignore them, add them to the ignore list in an\n`osv-scanner.toml` file located in the same directory as the lockfile containing the vulnerable dependency.\n\nSee the format and more options in our documentation here: https://google.github.io/osv-scanner/configuration/\n\nAdd or append these values to the following config files to ignore this vulnerability:\n\n\n`/path/to/osv-scanner.toml`\n```\n[[IgnoredVulns]]\nid = \"CVE-2021-3121\"\nreason = \"Your reason for ignoring this vulnerability\"\n```\n\n"
+                "text": "\n**Your dependency is vulnerable to [CVE-2021-3121](https://osv.dev/list?q=CVE-2021-3121)**.\n\n\n## [GO-2021-0053](https://osv.dev/vulnerability/GO-2021-0053)\n\n\u003cdetails\u003e\n\u003csummary\u003eDetails\u003c/summary\u003e\n\n\u003e Due to improper bounds checking, maliciously crafted input to generated Unmarshal methods can cause an out-of-bounds panic. If parsing messages from untrusted parties, this may be used as a denial of service vector.\n\n\u003c/details\u003e\n\n\n\n---\n\n### Affected Packages\n\n| Source | Package Name | Package Version |\n| --- | --- | --- |\n| lockfile:/path/to/go.mod | github.com/gogo/protobuf | 1.3.1 |\n\n## Remediation\n\n\n\nTo fix these vulnerabilities, update the vulnerabilities past the listed fixed versions below.\n\n### Fixed Versions\n\n| Vulnerability ID | Package Name | Fixed Version |\n| --- | --- | --- |\n| GO-2021-0053 | github.com/gogo/protobuf | 1.3.2 |\n\n\n\nIf you believe these vulnerabilities do not affect your code and wish to ignore them, add them to the ignore list in an\n`osv-scanner.toml` file located in the same directory as the lockfile containing the vulnerable dependency.\n\nSee the format and more options in our documentation here: https://google.github.io/osv-scanner/configuration/\n\nAdd or append these values to the following config files to ignore this vulnerability:\n\n\n`/path/to/osv-scanner.toml`\n```\n[[IgnoredVulns]]\nid = \"CVE-2021-3121\"\nreason = \"Your reason for ignoring this vulnerability\"\n```\n\n",
+                "markdown": "\n**Your dependency is vulnerable to [CVE-2021-3121](https://osv.dev/list?q=CVE-2021-3121)**.\n\n\n## [GO-2021-0053](https://osv.dev/vulnerability/GO-2021-0053)\n\n\u003cdetails\u003e\n\u003csummary\u003eDetails\u003c/summary\u003e\n\n\u003e Due to improper bounds checking, maliciously crafted input to generated Unmarshal methods can cause an out-of-bounds panic. If parsing messages from untrusted parties, this may be used as a denial of service vector.\n\n\u003c/details\u003e\n\n\n\n---\n\n### Affected Packages\n\n| Source | Package Name | Package Version |\n| --- | --- | --- |\n| lockfile:/path/to/go.mod | github.com/gogo/protobuf | 1.3.1 |\n\n## Remediation\n\n\n\nTo fix these vulnerabilities, update the vulnerabilities past the listed fixed versions below.\n\n### Fixed Versions\n\n| Vulnerability ID | Package Name | Fixed Version |\n| --- | --- | --- |\n| GO-2021-0053 | github.com/gogo/protobuf | 1.3.2 |\n\n\n\nIf you believe these vulnerabilities do not affect your code and wish to ignore them, add them to the ignore list in an\n`osv-scanner.toml` file located in the same directory as the lockfile containing the vulnerable dependency.\n\nSee the format and more options in our documentation here: https://google.github.io/osv-scanner/configuration/\n\nAdd or append these values to the following config files to ignore this vulnerability:\n\n\n`/path/to/osv-scanner.toml`\n```\n[[IgnoredVulns]]\nid = \"CVE-2021-3121\"\nreason = \"Your reason for ignoring this vulnerability\"\n```\n\n"
               }
             }
           ],
-          "version": "1.4.0"
+          "version": "1.4.1"
         }
       },
       "artifacts": [
diff --git a/internal/output/sarif_internal_test.go b/internal/output/sarif_internal_test.go
index 529a545..03e0de4 100644
--- a/internal/output/sarif_internal_test.go
+++ b/internal/output/sarif_internal_test.go
@@ -18,6 +18,10 @@ func Test_createSARIFHelpText(t *testing.T) {
 			gv:       testutility.LoadJSONFixture[groupedSARIFFinding](t, "fixtures/vuln-grouped.json"),
 			wantPath: "fixtures/sarif-output.md",
 		},
+		{
+			gv:       testutility.LoadJSONFixture[groupedSARIFFinding](t, "fixtures/commit-grouped.json"),
+			wantPath: "fixtures/sarif-commit-output.md",
+		},
 	}
 	for _, tt := range tests {
 		tt := tt
diff --git a/internal/output/sarif_test.go b/internal/output/sarif_test.go
index 99c4696..b609a53 100644
--- a/internal/output/sarif_test.go
+++ b/internal/output/sarif_test.go
@@ -67,7 +67,7 @@ func TestPrintSARIFReport(t *testing.T) {
 			if err != nil {
 				t.Errorf("Error writing SARIF output: %s", err)
 			}
-			testutility.CreateTextFixture(t, tt.wantPath, bufOut.String())
+			testutility.AssertMatchFixtureText(t, tt.wantPath, bufOut.String())
 		})
 	}
 }
diff --git a/pkg/lockfile/parse-yarn-lock-v1_test.go b/pkg/lockfile/parse-yarn-lock-v1_test.go
index 80e2679..c2363e7 100644
--- a/pkg/lockfile/parse-yarn-lock-v1_test.go
+++ b/pkg/lockfile/parse-yarn-lock-v1_test.go
@@ -183,10 +183,10 @@ func TestParseYarnLock_v1_ScopedPackages(t *testing.T) {
 	})
 }
 
-func TestParseYarnLock_v1_VersionsWithBuildString(t *testing.T) {
+func TestParseYarnLock_v1_WithPrerelease(t *testing.T) {
 	t.Parallel()
 
-	packages, err := lockfile.ParseYarnLock("fixtures/yarn/versions-with-build-strings.v1.lock")
+	packages, err := lockfile.ParseYarnLock("fixtures/yarn/with-prerelease.v1.lock")
 
 	if err != nil {
 		t.Errorf("Got unexpected error: %v", err)
@@ -226,6 +226,31 @@ func TestParseYarnLock_v1_VersionsWithBuildString(t *testing.T) {
 	})
 }
 
+func TestParseYarnLock_v1_WithBuildString(t *testing.T) {
+	t.Parallel()
+
+	packages, err := lockfile.ParseYarnLock("fixtures/yarn/with-build-string.v1.lock")
+
+	if err != nil {
+		t.Errorf("Got unexpected error: %v", err)
+	}
+
+	expectPackages(t, packages, []lockfile.PackageDetails{
+		{
+			Name:      "domino",
+			Version:   "2.1.6+git",
+			Ecosystem: lockfile.YarnEcosystem,
+			CompareAs: lockfile.YarnEcosystem,
+		},
+		{
+			Name:      "tslib",
+			Version:   "2.6.2",
+			Ecosystem: lockfile.YarnEcosystem,
+			CompareAs: lockfile.YarnEcosystem,
+		},
+	})
+}
+
 func TestParseYarnLock_v1_Commits(t *testing.T) {
 	t.Parallel()
 
diff --git a/pkg/lockfile/parse-yarn-lock-v2_test.go b/pkg/lockfile/parse-yarn-lock-v2_test.go
index 23d66ba..55959fa 100644
--- a/pkg/lockfile/parse-yarn-lock-v2_test.go
+++ b/pkg/lockfile/parse-yarn-lock-v2_test.go
@@ -158,10 +158,10 @@ func TestParseYarnLock_v2_ScopedPackages(t *testing.T) {
 	})
 }
 
-func TestParseYarnLock_v2_VersionsWithBuildString(t *testing.T) {
+func TestParseYarnLock_v2_WithPrerelease(t *testing.T) {
 	t.Parallel()
 
-	packages, err := lockfile.ParseYarnLock("fixtures/yarn/versions-with-build-strings.v2.lock")
+	packages, err := lockfile.ParseYarnLock("fixtures/yarn/with-prerelease.v2.lock")
 
 	if err != nil {
 		t.Errorf("Got unexpected error: %v", err)
@@ -189,6 +189,38 @@ func TestParseYarnLock_v2_VersionsWithBuildString(t *testing.T) {
 	})
 }
 
+func TestParseYarnLock_v2_WithBuildString(t *testing.T) {
+	t.Parallel()
+
+	packages, err := lockfile.ParseYarnLock("fixtures/yarn/with-build-string.v2.lock")
+
+	if err != nil {
+		t.Errorf("Got unexpected error: %v", err)
+	}
+
+	expectPackages(t, packages, []lockfile.PackageDetails{
+		{
+			Name:      "domino",
+			Version:   "2.1.6+git",
+			Commit:    "f2435fe1f9f7c91ade0bd472c4723e5eacd7d19a",
+			Ecosystem: lockfile.YarnEcosystem,
+			CompareAs: lockfile.YarnEcosystem,
+		},
+		{
+			Name:      "tslib",
+			Version:   "2.6.2",
+			Ecosystem: lockfile.YarnEcosystem,
+			CompareAs: lockfile.YarnEcosystem,
+		},
+		{
+			Name:      "zone.js",
+			Version:   "0.0.0-use.local",
+			Ecosystem: lockfile.YarnEcosystem,
+			CompareAs: lockfile.YarnEcosystem,
+		},
+	})
+}
+
 func TestParseYarnLock_v2_Commits(t *testing.T) {
 	t.Parallel()
 
diff --git a/pkg/osvscanner/vulnerability_result_internal_test.go b/pkg/osvscanner/vulnerability_result_internal_test.go
index 36b789e..73ccf51 100644
--- a/pkg/osvscanner/vulnerability_result_internal_test.go
+++ b/pkg/osvscanner/vulnerability_result_internal_test.go
@@ -26,7 +26,7 @@ func Test_groupResponseBySource(t *testing.T) {
 		tt := tt // Reinitialize for t.Parallel()
 		t.Run(tt.name, func(t *testing.T) {
 			t.Parallel()
-			if got := groupResponseBySource(tt.args.r, tt.args.query, tt.args.resp, tt.args.callAnalysis); !reflect.DeepEqual(got, tt.want) {
+			if got := buildVulnerabilityResults(tt.args.r, tt.args.query, tt.args.resp, tt.args.callAnalysis); !reflect.DeepEqual(got, tt.want) {
 				t.Errorf("groupResponse() = %v, want %v", got, tt.want)
 			}
 		})