Repository: google/osv-scanner
Pull request #559 (2023-09-28 01:04:18)

SARIF with fixed version
Add fixed version in help text + unit tests

Also add `osv-reporter` to scheduled scanning, this allows scheduled scanning to also print out the vulnerability table as well as the SARIF.

Updated the unit tests to show a git like diff output for text comparisons to make it easier to see where things changed from the last snapshot. This does pull in 1 additional dependency however: github.com/hexops/gotextdiff

codecov-commenter: ## [Codecov](https://app.codecov.io/gh/google/osv-scanner/pull/559?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) Report
> Merging [#559](https://app.codecov.io/gh/google/osv-scanner/pull/559?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) (7df0806) into [main](https://app.codecov.io/gh/google/osv-scanner/commit/81138016771dcd59a2432b981394f93a824d27b8?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) (8113801) will **increase** coverage by `0.10%`.
> The diff coverage is `97.05%`.

```diff
@@            Coverage Diff             @@
##             main     #559      +/-   ##
==========================================
+ Coverage   78.64%   78.75%   +0.10%     
==========================================
  Files          77       77              
  Lines        5273     5300      +27     
==========================================
+ Hits         4147     4174      +27     
  Misses        963      963              
  Partials      163      163              
```


| [Files](https://app.codecov.io/gh/google/osv-scanner/pull/559?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) | Coverage Δ | |
|---|---|---|
| [internal/output/sarif.go](https://app.codecov.io/gh/google/osv-scanner/pull/559?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google#diff-aW50ZXJuYWwvb3V0cHV0L3NhcmlmLmdv) | `92.85% <97.05%> (+1.36%)` | :arrow_up: |



Patch:
diff --git a/.github/workflows/osv-scanner-reusable.yml b/.github/workflows/osv-scanner-reusable.yml
index c26dfd6..5d55b21 100644
--- a/.github/workflows/osv-scanner-reusable.yml
+++ b/.github/workflows/osv-scanner-reusable.yml
@@ -38,9 +38,16 @@ jobs:
         uses: google/osv-scanner/actions/scanner@main
         with:
           scan-args: |-
-            --output=${{ inputs.results-file-name }}
-            --format=sarif
+            --output=results.json
+            --format=json
             ${{ inputs.scan-args }}
+      - name: "Run osv-scanner-reporter"
+        uses: google/osv-scanner/actions/reporter@main
+        with:
+          scan-args: |-
+            --output=${{ inputs.results-file-name }}
+            --new=results.json
+            --gh-annotations=false
       # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
       # format to the repository Actions tab.
       - name: "Upload artifact"
diff --git a/go.mod b/go.mod
index 4b86204..521c05b 100644
--- a/go.mod
+++ b/go.mod
@@ -9,6 +9,7 @@ require (
 	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/hexops/gotextdiff v1.0.3
 	github.com/jedib0t/go-pretty/v6 v6.4.7
 	github.com/kr/pretty v0.3.1
 	github.com/owenrumney/go-sarif/v2 v2.2.2
@@ -19,36 +20,35 @@ require (
 	golang.org/x/mod v0.12.0
 	golang.org/x/sync v0.3.0
 	golang.org/x/term v0.12.0
-	golang.org/x/vuln v1.0.0
+	golang.org/x/vuln v1.0.1
 	gopkg.in/yaml.v3 v3.0.1
 )
 
-require github.com/cyphar/filepath-securejoin v0.2.4 // indirect
-
 require (
 	// Vanity URL for https://github.com/imdario/mergo
 	dario.cat/mergo v1.0.0 // indirect
 	github.com/Microsoft/go-winio v0.6.1 // indirect
-	github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect
+	github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c // indirect
 	github.com/acomagu/bufpipe v1.0.4 // indirect
-	github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect
+	github.com/anchore/go-struct-converter v0.0.0-20230627203149-c72ef8859ca9 // indirect
 	github.com/cloudflare/circl v1.3.3 // indirect
 	github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
+	github.com/cyphar/filepath-securejoin v0.2.4 // indirect
 	github.com/emirpasic/gods v1.18.1 // indirect
 	github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
-	github.com/goark/errs v1.1.0 // indirect
+	github.com/goark/errs v1.3.2 // indirect
 	github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
 	github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab
 	github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
 	github.com/kevinburke/ssh_config v1.2.0 // indirect
 	github.com/kr/text v0.2.0 // indirect
-	github.com/mattn/go-runewidth v0.0.13 // indirect
+	github.com/mattn/go-runewidth v0.0.15 // indirect
 	github.com/pjbgf/sha1cd v0.3.0 // indirect
-	github.com/rivo/uniseg v0.2.0 // indirect
+	github.com/rivo/uniseg v0.4.4 // indirect
 	github.com/rogpeppe/go-internal v1.11.0 // indirect
 	github.com/russross/blackfriday/v2 v2.1.0 // indirect
-	github.com/sergi/go-diff v1.1.0 // indirect
-	github.com/skeema/knownhosts v1.2.0 // indirect
+	github.com/sergi/go-diff v1.3.1 // indirect
+	github.com/skeema/knownhosts v1.2.1 // indirect
 	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
diff --git a/go.sum b/go.sum
index 5d03999..7bbc3d8 100644
--- a/go.sum
+++ b/go.sum
@@ -9,10 +9,14 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc
 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=
 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
 github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
@@ -41,6 +45,8 @@ github.com/go-git/go-git/v5 v5.9.0 h1:cD9SFA7sHVRdJ7AYck1ZaAa/yeuBvGPxwXDL8cxrOb
 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=
 github.com/goark/go-cvss v1.6.6/go.mod h1:H3qbfUSUlV7XtA3EwWNunvXz6OySwWHOuO+R6ZPMQPI=
 github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
@@ -50,6 +56,8 @@ github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaW
 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/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=
@@ -69,7 +77,10 @@ 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=
@@ -85,6 +96,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
 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=
 github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
 github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
 github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
@@ -92,9 +105,13 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf
 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=
 github.com/spdx/gordf v0.0.0-20221230105357-b735bd5aac89 h1:dArkMwZ7Mf2JiU8OfdmqIv8QaHT4oyifLIe1UhsF1SY=
 github.com/spdx/gordf v0.0.0-20221230105357-b735bd5aac89/go.mod h1:uKWaldnbMnjsSAXRurWqqrdyZen1R7kxl8TkmWk2OyM=
@@ -195,6 +212,8 @@ 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/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=
 google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
diff --git a/internal/output/fixtures/sarif-output.md b/internal/output/fixtures/sarif-output.md
new file mode 100644
index 0000000..3043493
--- /dev/null
+++ b/internal/output/fixtures/sarif-output.md
@@ -0,0 +1,138 @@
+
+**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), ).
+
+
+## [RUSTSEC-2022-0013](https://osv.dev/vulnerability/RUSTSEC-2022-0013)
+
+<details>
+<summary>Details</summary>
+
+> 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.
+> 
+> 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.
+> 
+> ## Overview
+> 
+> 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.
+> 
+> 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.
+> 
+> ## Affected versions
+> 
+> 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.
+> 
+> ## Mitigations
+> 
+> We recommend everyone accepting user-controlled regexes to upgrade immediately
+> to the latest version of the `regex` crate.
+> 
+> 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.
+> 
+> ## Acknowledgements
+> 
+> We want to thank Addison Crump for responsibly disclosing this to us according
+> to the [Rust security policy][1], and for helping review the fix.
+> 
+> We also want to thank Andrew Gallant for developing the fix, and Pietro Albini
+> for coordinating the disclosure and writing this advisory.
+> 
+> [1]: https://www.rust-lang.org/policies/security
+
+</details>
+
+
+
+## [GHSA-m5pq-gvj9-9vr8](https://osv.dev/vulnerability/GHSA-m5pq-gvj9-9vr8)
+
+<details>
+<summary>Details</summary>
+
+> > This is a cross-post of [the official security advisory][advisory]. The official advisory contains a signed version with our PGP key, as well.
+> 
+> [advisory]: https://groups.google.com/g/rustlang-security-announcements/c/NcNNL1Jq7Yw
+> 
+> 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.
+> 
+> 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.
+> 
+> ## Overview
+> 
+> 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.
+> 
+> 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.
+> 
+> ## Affected versions
+> 
+> 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.
+> 
+> ## Mitigations
+> 
+> We recommend everyone accepting user-controlled regexes to upgrade immediately to the latest version of the `regex` crate.
+> 
+> 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.
+> 
+> ## Acknowledgements
+> 
+> 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.
+> 
+> We also want to thank Andrew Gallant for developing the fix, and Pietro Albini for coordinating the disclosure and writing this advisory.
+
+</details>
+
+
+
+---
+
+### Affected Packages
+| Source | Package Name | Package Version |
+| --- | --- | --- |
+| lockfile:/path/to/sub-rust-project/Cargo.lock | regex | 1.5.1 |
+
+## Remediation
+
+
+
+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.
+
+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/sub-rust-project/osv-scanner.toml`
+```
+[[IgnoredVulns]]
+id = "CVE-2022-24713"
+reason = "Your reason for ignoring this vulnerability"
+```
+
diff --git a/internal/output/fixtures/vuln-grouped.json b/internal/output/fixtures/vuln-grouped.json
new file mode 100644
index 0000000..78463b4
--- /dev/null
+++ b/internal/output/fixtures/vuln-grouped.json
@@ -0,0 +1,206 @@
+{
+  "DisplayID": "CVE-2022-24713",
+  "PkgSource": [
+    {
+      "Package": {
+        "name": "regex",
+        "version": "1.5.1",
+        "ecosystem": "crates.io",
+        "commit": ""
+      },
+      "Source": {
+        "path": "/path/to/sub-rust-project/Cargo.lock",
+        "type": "lockfile"
+      }
+    }
+  ],
+  "AliasedVulns": {
+    "GHSA-m5pq-gvj9-9vr8": {
+      "modified": "2022-08-11T20:38:52Z",
+      "published": "2022-03-08T20:00:36Z",
+      "schema_version": "1.4.0",
+      "id": "GHSA-m5pq-gvj9-9vr8",
+      "aliases": [
+        "CVE-2022-24713"
+      ],
+      "summary": "Rust's regex crate vulnerable to regular expression denial of service",
+      "details": "\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\n[advisory]: https://groups.google.com/g/rustlang-security-announcements/c/NcNNL1Jq7Yw\n\nThe 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\nThis 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\n## Overview\n\nThe `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\nUnfortunately 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\n## Affected versions\n\nAll 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\n## Mitigations\n\nWe recommend everyone accepting user-controlled regexes to upgrade immediately to the latest version of the `regex` crate.\n\nUnfortunately 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\n## Acknowledgements\n\nWe 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\nWe also want to thank Andrew Gallant for developing the fix, and Pietro Albini for coordinating the disclosure and writing this advisory.",
+      "affected": [
+        {
+          "package": {
+            "ecosystem": "crates.io",
+            "name": "regex",
+            "purl": "pkg:cargo/regex"
+          },
+          "ranges": [
+            {
+              "type": "SEMVER",
+              "events": [
+                {
+                  "introduced": "0"
+                },
+                {
+                  "fixed": "1.5.5"
+                }
+              ]
+            }
+          ],
+          "database_specific": {
+            "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2022/03/GHSA-m5pq-gvj9-9vr8/GHSA-m5pq-gvj9-9vr8.json"
+          }
+        }
+      ],
+      "severity": [
+        {
+          "type": "CVSS_V3",
+          "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
+        }
+      ],
+      "references": [
+        {
+          "type": "WEB",
+          "url": "https://github.com/rust-lang/regex/security/advisories/GHSA-m5pq-gvj9-9vr8"
+        },
+        {
+          "type": "ADVISORY",
+          "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-24713"
+        },
+        {
+          "type": "WEB",
+          "url": "https://github.com/rust-lang/regex/commit/ae70b41d4f46641dbc45c7a4f87954aea356283e"
+        },
+        {
+          "type": "PACKAGE",
+          "url": "https://github.com/rust-lang/regex/"
+        },
+        {
+          "type": "WEB",
+          "url": "https://groups.google.com/g/rustlang-security-announcements/c/NcNNL1Jq7Yw"
+        },
+        {
+          "type": "WEB",
+          "url": "https://lists.debian.org/debian-lts-announce/2022/04/msg00003.html"
+        },
+        {
+          "type": "WEB",
+          "url": "https://lists.debian.org/debian-lts-announce/2022/04/msg00009.html"
+        },
+        {
+          "type": "WEB",
+          "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/JANLZ3JXWJR7FSHE57K66UIZUIJZI67T/"
+        },
+        {
+          "type": "WEB",
+          "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/O3YB7CURSG64CIPCDPNMGPE4UU24AB6H/"
+        },
+        {
+          "type": "WEB",
+          "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/PDOWTHNVGBOP2HN27PUFIGRYNSNDTYRJ/"
+        },
+        {
+          "type": "WEB",
+          "url": "https://rustsec.org/advisories/RUSTSEC-2022-0013.html"
+        },
+        {
+          "type": "WEB",
+          "url": "https://security.gentoo.org/glsa/202208-08"
+        },
+        {
+          "type": "WEB",
+          "url": "https://security.gentoo.org/glsa/202208-14"
+        },
+        {
+          "type": "WEB",
+          "url": "https://www.debian.org/security/2022/dsa-5113"
+        },
+        {
+          "type": "WEB",
+          "url": "https://www.debian.org/security/2022/dsa-5118"
+        }
+      ],
+      "database_specific": {
+        "cwe_ids": [
+          "CWE-400"
+        ],
+        "github_reviewed": true,
+        "github_reviewed_at": "2022-03-08T20:00:36Z",
+        "nvd_published_at": "2022-03-08T19:15:00Z",
+        "severity": "HIGH"
+      }
+    },
+    "RUSTSEC-2022-0013": {
+      "modified": "2023-06-13T13:10:24Z",
+      "published": "2022-03-08T12:00:00Z",
+      "schema_version": "1.4.0",
+      "id": "RUSTSEC-2022-0013",
+      "aliases": [
+        "CVE-2022-24713",
+        "GHSA-m5pq-gvj9-9vr8"
+      ],
+      "summary": "Regexes with large repetitions on empty sub-expressions take a very long time to parse",
+      "details": "The Rust Security Response WG was notified that the `regex` crate did not\nproperly limit the complexity of the regular expressions (regex) it parses. An\nattacker could use this security issue to perform a denial of service, by\nsending a specially crafted regex to a service accepting untrusted regexes. No\nknown vulnerability is present when parsing untrusted input with trusted\nregexes.\n\nThis issue has been assigned CVE-2022-24713. The severity of this vulnerability\nis \"high\" when the `regex` crate is used to parse untrusted regexes. Other uses\nof the `regex` crate are not affected by this vulnerability.\n\n## Overview\n\nThe `regex` crate features built-in mitigations to prevent denial of service\nattacks caused by untrusted regexes, or untrusted input matched by trusted\nregexes. Those (tunable) mitigations already provide sane defaults to prevent\nattacks. This guarantee is documented and it's considered part of the crate's\nAPI.\n\nUnfortunately a bug was discovered in the mitigations designed to prevent\nuntrusted regexes to take an arbitrary amount of time during parsing, and it's\npossible to craft regexes that bypass such mitigations. This makes it possible\nto perform denial of service attacks by sending specially crafted regexes to\nservices accepting user-controlled, untrusted regexes.\n\n## Affected versions\n\nAll versions of the `regex` crate before or equal to 1.5.4 are affected by this\nissue. The fix is include starting from  `regex` 1.5.5.\n\n## Mitigations\n\nWe recommend everyone accepting user-controlled regexes to upgrade immediately\nto the latest version of the `regex` crate.\n\nUnfortunately there is no fixed set of problematic regexes, as there are\npractically infinite regexes that could be crafted to exploit this\nvulnerability. Because of this, we do not recommend denying known problematic\nregexes.\n\n## Acknowledgements\n\nWe want to thank Addison Crump for responsibly disclosing this to us according\nto the [Rust security policy][1], and for helping review the fix.\n\nWe also want to thank Andrew Gallant for developing the fix, and Pietro Albini\nfor coordinating the disclosure and writing this advisory.\n\n[1]: https://www.rust-lang.org/policies/security",
+      "affected": [
+        {
+          "package": {
+            "ecosystem": "crates.io",
+            "name": "regex",
+            "purl": "pkg:cargo/regex"
+          },
+          "ranges": [
+            {
+              "type": "SEMVER",
+              "events": [
+                {
+                  "introduced": "0.0.0-0"
+                },
+                {
+                  "fixed": "1.5.5"
+                }
+              ]
+            }
+          ],
+          "database_specific": {
+            "categories": [
+              "denial-of-service"
+            ],
+            "cvss": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
+            "informational": null,
+            "source": "https://github.com/rustsec/advisory-db/blob/osv/crates/RUSTSEC-2022-0013.json"
+          },
+          "ecosystem_specific": {
+            "affects": {
+              "arch": [],
+              "functions": [],
+              "os": []
+            }
+          }
+        }
+      ],
+      "severity": [
+        {
+          "type": "CVSS_V3",
+          "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
+        }
+      ],
+      "references": [
+        {
+          "type": "PACKAGE",
+          "url": "https://crates.io/crates/regex"
+        },
+        {
+          "type": "ADVISORY",
+          "url": "https://rustsec.org/advisories/RUSTSEC-2022-0013.html"
+        },
+        {
+          "type": "WEB",
+          "url": "https://groups.google.com/g/rustlang-security-announcements/c/NcNNL1Jq7Yw"
+        }
+      ]
+    }
+  },
+  "AliasedIDList": [
+    "CVE-2022-24713",
+    "RUSTSEC-2022-0013",
+    "GHSA-m5pq-gvj9-9vr8"
+  ]
+}
diff --git a/internal/output/sarif.go b/internal/output/sarif.go
index 07a5418..5ff47a9 100644
--- a/internal/output/sarif.go
+++ b/internal/output/sarif.go
@@ -12,31 +12,46 @@ import (
 	"github.com/google/osv-scanner/pkg/models"
 	"github.com/jedib0t/go-pretty/v6/table"
 	"github.com/owenrumney/go-sarif/v2/sarif"
+	"golang.org/x/exp/maps"
 	"golang.org/x/exp/slices"
 )
 
 type HelpTemplateData struct {
 	ID                    string
 	AffectedPackagesTable string
+	AffectedPackagePaths  []string
 	AliasedVulns          []VulnDescription
+	HasFixedVersion       bool
+	FixedVersionTable     string
 }
 
+type FixedPkgTableData struct {
+	VulnID       string
+	PackageName  string
+	FixedVersion string
+}
 type VulnDescription struct {
 	ID      string
 	Details string
 }
 
+// Two double-quotes ("") is replaced with a single backtick (`), since we can't embed backticks in raw strings
 const SARIFTemplate = `
-**Your dependency is vulnerable to [{{.ID}}](https://osv.dev/vulnerability/{{.ID}})** 
+**Your dependency is vulnerable to [{{.ID}}](https://osv.dev/list?q={{.ID}})**
 {{- if gt (len .AliasedVulns) 1 }}
-(Also published as: {{range .AliasedVulns -}} {{if ne .ID $.ID}} [{{.ID}}](https://osv.dev/vulnerability/{{.ID}}) {{end}}{{end}})
+(Also published as: {{range .AliasedVulns -}} {{if ne .ID $.ID}} [{{.ID}}](https://osv.dev/vulnerability/{{.ID}}), {{end}}{{end}})
 {{- end}}.
 
 {{range .AliasedVulns}}
-> ## [{{.ID}}](https://osv.dev/vulnerability/{{.ID}})
-> 
+## [{{.ID}}](https://osv.dev/vulnerability/{{.ID}})
+
+<details>
+<summary>Details</summary>
+
 > {{.Details}}
-> 
+
+</details>
+
 
 {{end}}
 ---
@@ -44,6 +59,31 @@ const SARIFTemplate = `
 ### Affected Packages
 {{.AffectedPackagesTable}}
 
+## Remediation
+
+{{if .HasFixedVersion}}
+
+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
+""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:
+
+{{range .AffectedPackagePaths}}
+""{{.}}/osv-scanner.toml""
+""""""
+[[IgnoredVulns]]
+id = "{{$.ID}}"
+reason = "Your reason for ignoring this vulnerability"
+""""""
+{{end}}
 `
 
 // GroupFixedVersions builds the fixed versions for each ID Group, with keys formatted like so:
@@ -74,12 +114,12 @@ func GroupFixedVersions(flattened []models.VulnerabilityFlattened) map[string][]
 	return groupFixedVersions
 }
 
-// createSARIFHelpTable creates a vulnerability table which includes the fixed versions for a specific source file
-func createSARIFHelpTable(pkgWithSrc map[pkgWithSource]struct{}) table.Writer {
+// createSARIFAffectedPkgTable creates a vulnerability table which includes the affected versions for a specific source file
+func createSARIFAffectedPkgTable(pkgWithSrc []pkgWithSource) table.Writer {
 	helpTable := table.NewWriter()
 	helpTable.AppendHeader(table.Row{"Source", "Package Name", "Package Version"})
 
-	for ps := range pkgWithSrc {
+	for _, ps := range pkgWithSrc {
 		helpTable.AppendRow(table.Row{
 			ps.Source.String(),
 			ps.Package.Name,
@@ -90,6 +130,26 @@ func createSARIFHelpTable(pkgWithSrc map[pkgWithSource]struct{}) table.Writer {
 	return helpTable
 }
 
+// createSARIFFixedPkgTable creates a vulnerability table which includes the fixed versions for a specific source file
+func createSARIFFixedPkgTable(fixedPkgTableData []FixedPkgTableData) table.Writer {
+	helpTable := table.NewWriter()
+	helpTable.AppendHeader(table.Row{"Vulnerability ID", "Package Name", "Fixed Version"})
+
+	slices.SortFunc(fixedPkgTableData, func(a, b FixedPkgTableData) int {
+		return strings.Compare(a.VulnID, b.VulnID)
+	})
+
+	for _, data := range fixedPkgTableData {
+		helpTable.AppendRow(table.Row{
+			data.VulnID,
+			data.PackageName,
+			data.FixedVersion,
+		})
+	}
+
+	return helpTable
+}
+
 // stripGitHubWorkspace strips /github/workspace/ from the given path.
 func stripGitHubWorkspace(path string) string {
 	return strings.TrimPrefix(path, "/github/workspace/")
@@ -97,15 +157,27 @@ func stripGitHubWorkspace(path string) string {
 
 // createSARIFHelpText returns the text for SARIF rule's help field
 func createSARIFHelpText(gv *groupedSARIFFinding) string {
-	helpTable := createSARIFHelpTable(gv.PkgSource)
-
-	helpTextTemplate, err := template.New("helpText").Parse(SARIFTemplate)
+	backtickSARIFTemplate := strings.ReplaceAll(SARIFTemplate, `""`, "`")
+	helpTextTemplate, err := template.New("helpText").Parse(backtickSARIFTemplate)
 	if err != nil {
-		log.Panicf("failed to parse sarif help text template")
+		log.Panicf("failed to parse sarif help text template: %v", err)
 	}
 
 	vulnDescriptions := []VulnDescription{}
+	fixedPkgTableData := []FixedPkgTableData{}
+
+	hasFixedVersion := false
 	for _, v := range gv.AliasedVulns {
+		for p, v2 := range v.FixedVersions() {
+			slices.Sort(v2)
+			fixedPkgTableData = append(fixedPkgTableData, FixedPkgTableData{
+				PackageName:  p.Name,
+				FixedVersion: strings.Join(slices.Compact(v2), ", "),
+				VulnID:       v.ID,
+			})
+			hasFixedVersion = true
+		}
+
 		vulnDescriptions = append(vulnDescriptions, VulnDescription{
 			ID:      v.ID,
 			Details: strings.ReplaceAll(v.Details, "\n", "\n> "),
@@ -115,10 +187,29 @@ func createSARIFHelpText(gv *groupedSARIFFinding) string {
 
 	helpText := strings.Builder{}
 
+	pkgWithSrcKeys := maps.Keys(gv.PkgSource)
+	slices.SortFunc(pkgWithSrcKeys, func(a, b pkgWithSource) int {
+		// This doesn't take into account multiple packages within the same source file
+		// which will still be non deterministic. But since that is a rare edge case,
+		// no need to add significant extra logic here to make it deterministic.
+		return strings.Compare(a.Source.Path, b.Source.Path)
+	})
+
+	affectedPackagePaths := []string{}
+	for _, pws := range pkgWithSrcKeys {
+		affectedPackagePaths = append(affectedPackagePaths, stripGitHubWorkspace(filepath.Dir(pws.Source.Path)))
+	}
+	// Compact to remove duplicates
+	// (which should already be next to each other since it's sorted in the previous step)
+	affectedPackagePaths = slices.Compact(affectedPackagePaths)
+
 	err = helpTextTemplate.Execute(&helpText, HelpTemplateData{
 		ID:                    gv.DisplayID,
-		AffectedPackagesTable: helpTable.RenderMarkdown(),
+		AffectedPackagesTable: createSARIFAffectedPkgTable(pkgWithSrcKeys).RenderMarkdown(),
 		AliasedVulns:          vulnDescriptions,
+		HasFixedVersion:       hasFixedVersion,
+		FixedVersionTable:     createSARIFFixedPkgTable(fixedPkgTableData).RenderMarkdown(),
+		AffectedPackagePaths:  affectedPackagePaths,
 	})
 
 	if err != nil {


Test patch:
diff --git a/cmd/osv-scanner/main_test.go b/cmd/osv-scanner/main_test.go
index 1890b2d..b62d078 100644
--- a/cmd/osv-scanner/main_test.go
+++ b/cmd/osv-scanner/main_test.go
@@ -370,8 +370,8 @@ func TestRun(t *testing.T) {
 			name:         "Sarif with vulns",
 			args:         []string{"", "--format", "sarif", "--config", "./fixtures/osv-scanner-empty-config.toml", "./fixtures/locks-many/package-lock.json"},
 			wantExitCode: 1,
-			wantStdout: fmt.Sprintf(`
-            {
+			wantStdout: fmt.Sprint(`
+						{
               "version": "2.1.0",
               "$schema": "https://json.schemastore.org/sarif-2.1.0.json",
               "runs": [
@@ -395,12 +395,12 @@ func TestRun(t *testing.T) {
                             "GHSA-whgm-jr23-g3j9"
                           ],
                           "help": {
-                            "text": "\n**Your dependency is vulnerable to [CVE-2021-23424](https://osv.dev/vulnerability/CVE-2021-23424)**.\n\n\n\u003e ## [GHSA-whgm-jr23-g3j9](https://osv.dev/vulnerability/GHSA-whgm-jr23-g3j9)\n\u003e \n\u003e This affects all versions of package ansi-html. If an attacker provides a malicious string, it will get stuck processing the input for an extremely long time.\n\u003e \n\n\n---\n\n### Affected Packages\n| Source | Package Name | Package Version |\n| --- | --- | --- |\n| lockfile:<rootdir>/fixtures/locks-many/package-lock.json | ansi-html | 0.0.1 |\n\n",
-                            "markdown": "\n**Your dependency is vulnerable to [CVE-2021-23424](https://osv.dev/vulnerability/CVE-2021-23424)**.\n\n\n\u003e ## [GHSA-whgm-jr23-g3j9](https://osv.dev/vulnerability/GHSA-whgm-jr23-g3j9)\n\u003e \n\u003e This affects all versions of package ansi-html. If an attacker provides a malicious string, it will get stuck processing the input for an extremely long time.\n\u003e \n\n\n---\n\n### Affected Packages\n| Source | Package Name | Package Version |\n| --- | --- | --- |\n| lockfile:<rootdir>/fixtures/locks-many/package-lock.json | ansi-html | 0.0.1 |\n\n"
+                            "text": "%%",
+                            "markdown": "%%"
                           }
                         }
                       ],
-                      "version": "%s"
+                      "version": "`, version.OSVVersion, `"
                     }
                   },
                   "artifacts": [
@@ -433,7 +433,7 @@ func TestRun(t *testing.T) {
                 }
               ]
             }
-			`, version.OSVVersion),
+			`),
 			wantStderr: `
 				Scanning dir ./fixtures/locks-many/package-lock.json
 				Scanned <rootdir>/fixtures/locks-many/package-lock.json file and found 1 package
diff --git a/internal/output/fixtures/test-vuln-results-a.sarif b/internal/output/fixtures/test-vuln-results-a.sarif
index f15ca33..ea1ca9f 100644
--- a/internal/output/fixtures/test-vuln-results-a.sarif
+++ b/internal/output/fixtures/test-vuln-results-a.sarif
@@ -23,8 +23,8 @@
                 "GHSA-m5pq-gvj9-9vr8"
               ],
               "help": {
-                "text": "\n**Your dependency is vulnerable to [CVE-2022-24713](https://osv.dev/vulnerability/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\u003e ## [RUSTSEC-2022-0013](https://osv.dev/vulnerability/RUSTSEC-2022-0013)\n\u003e \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\u003e \n\n\n\u003e ## [GHSA-m5pq-gvj9-9vr8](https://osv.dev/vulnerability/GHSA-m5pq-gvj9-9vr8)\n\u003e \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\u003e \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",
-                "markdown": "\n**Your dependency is vulnerable to [CVE-2022-24713](https://osv.dev/vulnerability/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\u003e ## [RUSTSEC-2022-0013](https://osv.dev/vulnerability/RUSTSEC-2022-0013)\n\u003e \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\u003e \n\n\n\u003e ## [GHSA-m5pq-gvj9-9vr8](https://osv.dev/vulnerability/GHSA-m5pq-gvj9-9vr8)\n\u003e \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\u003e \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"
+                "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"
               }
             },
             {
@@ -42,8 +42,8 @@
                 "GHSA-c3h9-896r-86jm"
               ],
               "help": {
-                "text": "\n**Your dependency is vulnerable to [CVE-2021-3121](https://osv.dev/vulnerability/CVE-2021-3121)**.\n\n\n\u003e ## [GO-2021-0053](https://osv.dev/vulnerability/GO-2021-0053)\n\u003e \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\u003e \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",
-                "markdown": "\n**Your dependency is vulnerable to [CVE-2021-3121](https://osv.dev/vulnerability/CVE-2021-3121)**.\n\n\n\u003e ## [GO-2021-0053](https://osv.dev/vulnerability/GO-2021-0053)\n\u003e \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\u003e \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"
+                "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"
               }
             }
           ],
diff --git a/internal/output/sarif_internal_test.go b/internal/output/sarif_internal_test.go
new file mode 100644
index 0000000..529a545
--- /dev/null
+++ b/internal/output/sarif_internal_test.go
@@ -0,0 +1,30 @@
+package output
+
+import (
+	"testing"
+
+	"github.com/google/osv-scanner/internal/testutility"
+)
+
+func Test_createSARIFHelpText(t *testing.T) {
+	t.Parallel()
+
+	tests := []struct {
+		name     string
+		gv       groupedSARIFFinding
+		wantPath string
+	}{
+		{
+			gv:       testutility.LoadJSONFixture[groupedSARIFFinding](t, "fixtures/vuln-grouped.json"),
+			wantPath: "fixtures/sarif-output.md",
+		},
+	}
+	for _, tt := range tests {
+		tt := tt
+		t.Run(tt.name, func(t *testing.T) {
+			t.Parallel()
+			sarifHelpText := createSARIFHelpText(&tt.gv)
+			testutility.AssertMatchFixtureText(t, tt.wantPath, sarifHelpText)
+		})
+	}
+}
diff --git a/internal/output/sarif_test.go b/internal/output/sarif_test.go
index b609a53..99c4696 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.AssertMatchFixtureText(t, tt.wantPath, bufOut.String())
+			testutility.CreateTextFixture(t, tt.wantPath, bufOut.String())
 		})
 	}
 }
diff --git a/internal/testutility/utility.go b/internal/testutility/utility.go
index 86bdd31..a55d27d 100644
--- a/internal/testutility/utility.go
+++ b/internal/testutility/utility.go
@@ -2,11 +2,15 @@ package testutility
 
 import (
 	"encoding/json"
+	"fmt"
 	"os"
 	"reflect"
 	"strings"
 	"testing"
 
+	"github.com/hexops/gotextdiff"
+	"github.com/hexops/gotextdiff/myers"
+	"github.com/hexops/gotextdiff/span"
 	"github.com/kr/pretty"
 )
 
@@ -77,15 +81,22 @@ func CreateTextFixture(t *testing.T, path string, val string) {
 	}
 }
 
-// AssertMatchFixtureText matches the Text file at path with val
-func AssertMatchFixtureText(t *testing.T, path string, val string) {
+// AssertMatchFixtureText matches the Text file at path with actual
+func AssertMatchFixtureText(t *testing.T, path string, actual string) {
 	t.Helper()
 	fileA, err := os.ReadFile(path)
 	if err != nil {
 		t.Fatalf("Failed to open fixture: %s", err)
 	}
 
-	if val != string(fileA) {
-		t.Errorf("Not equal: \ngot: \n%s\n\n---\nwant:\n%s", val, string(fileA))
+	expect := string(fileA)
+	if actual != string(fileA) {
+		if os.Getenv("TEST_NO_DIFF") == "true" {
+			t.Errorf("\nactual %s does not match expected:\n got:\n%s\n\n want:\n%s", path, actual, expect)
+		} else {
+			edits := myers.ComputeEdits(span.URIFromPath(path), expect, actual)
+			diff := fmt.Sprint(gotextdiff.ToUnified(path, "test-output", expect, edits))
+			t.Errorf("\nactual %s does not match expected:\n%s", path, diff)
+		}
 	}
 }