Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package grype for openSUSE:Factory checked 
in at 2026-10-07 19:33:24
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/grype (Old)
 and      /work/SRC/openSUSE:Factory/.grype.new.3698736 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "grype"

Wed Oct  7 19:33:24 2026 rev:131 rq:1382905 version:0.120.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/grype/grype.changes      2026-10-05 
13:03:19.435096620 +0200
+++ /work/SRC/openSUSE:Factory/.grype.new.3698736/grype.changes 2026-10-07 
19:33:57.247020498 +0200
@@ -1,0 +2,25 @@
+Wed Oct 07 05:01:48 UTC 2026 - Johannes Kastl 
<[email protected]>
+
+- Update to version 0.120.1:
+  * Bug Fixes
+    - run unit tests on windows and fix the handle leaks it
+      surfaced [PR #3766]
+    - Table presenter appends a spurious ", ..." to the FIX column
+      when all fix versions are already shown [Issue #3760] [PR
+      #3770]
+  * Dependencies
+    9 dependency changes (9 updated).
+    - Updated (9 packages)
+      - github.com/anchore/go-rpmdb v0.2.1 → v0.2.2
+      - github.com/anchore/stereoscope v0.3.3 → v0.3.4
+      - github.com/anchore/syft v1.54.0 → v1.54.1
+      - github.com/docker/cli v29.8.1+incompatible →
+        v29.8.2+incompatible
+      - github.com/klauspost/compress v1.20.0 → v1.20.1
+      - github.com/secure-systems-lab/go-securesystemslib v0.11.0 →
+        v0.11.1
+      - github.com/sigstore/protobuf-specs v0.5.1 → v0.5.2
+      - github.com/sigstore/sigstore v1.10.8 → v1.10.11
+      - github.com/sylabs/sif/v2 v2.24.1 → v2.24.2
+
+-------------------------------------------------------------------

Old:
----
  grype-0.120.0.obscpio

New:
----
  grype-0.120.1.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ grype.spec ++++++
--- /var/tmp/diff_new_pack.MDryGX/_old  2026-10-07 19:33:59.670121692 +0200
+++ /var/tmp/diff_new_pack.MDryGX/_new  2026-10-07 19:33:59.671121734 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           grype
-Version:        0.120.0
+Version:        0.120.1
 Release:        0
 Summary:        A vulnerability scanner for container images and filesystems
 License:        Apache-2.0

++++++ _service ++++++
--- /var/tmp/diff_new_pack.MDryGX/_old  2026-10-07 19:33:59.716123613 +0200
+++ /var/tmp/diff_new_pack.MDryGX/_new  2026-10-07 19:33:59.720123780 +0200
@@ -3,7 +3,7 @@
     <param name="url">https://github.com/anchore/grype.git</param>
     <param name="scm">git</param>
     <param name="exclude">.git</param>
-    <param name="revision">refs/tags/v0.120.0</param>
+    <param name="revision">refs/tags/v0.120.1</param>
     <param name="match-tag">v*</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="versionrewrite-pattern">v(.*)</param>

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.MDryGX/_old  2026-10-07 19:33:59.765125659 +0200
+++ /var/tmp/diff_new_pack.MDryGX/_new  2026-10-07 19:33:59.770125868 +0200
@@ -3,6 +3,6 @@
                 <param name="url">https://github.com/anchore/grype</param>
               <param 
name="changesrevision">fa8b7e2a528cf1f8b098123f256c61db9e5df69c</param></service><service
 name="tar_scm">
                 <param name="url">https://github.com/anchore/grype.git</param>
-              <param 
name="changesrevision">10fbc043ecbaf8436daa9efac9f1632557caf277</param></service></servicedata>
+              <param 
name="changesrevision">6f8d854af29d3a3086b11a84afa51554a2a245fe</param></service></servicedata>
 (No newline at EOF)
 

++++++ grype-0.120.0.obscpio -> grype-0.120.1.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/.golangci.yaml 
new/grype-0.120.1/.golangci.yaml
--- old/grype-0.120.0/.golangci.yaml    2026-10-02 15:23:52.000000000 +0200
+++ new/grype-0.120.1/.golangci.yaml    2026-10-06 18:42:08.000000000 +0200
@@ -1,4 +1,9 @@
 version: "2"
+run:
+  # keep in sync with buildTags in .make/main.go
+  build-tags:
+    - containers_image_openpgp
+    - exclude_graphdriver_btrfs
 linters:
     # inverted configuration with `enable-all` and `disable` is not scalable 
during updates of golangci-lint
   default: none
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/.goreleaser.yaml 
new/grype-0.120.1/.goreleaser.yaml
--- old/grype-0.120.0/.goreleaser.yaml  2026-10-02 15:23:52.000000000 +0200
+++ new/grype-0.120.1/.goreleaser.yaml  2026-10-06 18:42:08.000000000 +0200
@@ -13,6 +13,7 @@
   - id: linux-build
     dir: ./cmd/grype
     binary: grype
+    tags: [containers_image_openpgp, exclude_graphdriver_btrfs]
     goos:
       - linux
     goarch:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/.make/main.go 
new/grype-0.120.1/.make/main.go
--- old/grype-0.120.0/.make/main.go     2026-10-02 15:23:52.000000000 +0200
+++ new/grype-0.120.1/.make/main.go     2026-10-06 18:42:08.000000000 +0200
@@ -3,9 +3,12 @@
 import (
        "fmt"
        "os"
+       "path/filepath"
+       "runtime"
        "strings"
 
        . "github.com/anchore/go-make"
+       "github.com/anchore/go-make/config"
        "github.com/anchore/go-make/file"
        "github.com/anchore/go-make/lang"
        "github.com/anchore/go-make/log"
@@ -20,6 +23,12 @@
        snapshotBn = "snapshot" // goreleaser dist dir
 )
 
+// buildTags must match the linux build in .goreleaser.yaml so tests and lint 
compile the same code that ships
+// (containers_image_openpgp compiles in stereoscope's real containers-storage 
provider instead of its stub).
+// exclude_graphdriver_btrfs drops the cgo-only btrfs driver, which needs 
libbtrfs headers whenever cgo is on (e.g.
+// under -race); release builds are CGO_ENABLED=0 and never include it anyway.
+const buildTags = "containers_image_openpgp,exclude_graphdriver_btrfs"
+
 func main() {
        Makefile(
                golint.Tasks(golint.SkipTests()),
@@ -27,12 +36,14 @@
                        gotest.CoverageThreshold(47),
                        // excludes both anchore/grype/test/** and 
anchore/grype/internal/test/**
                        gotest.ExcludeGlob("**/test/**"),
+                       gotest.Tags(buildTags),
                ),
                goreleaser.Tasks(),
 
                buildTask(),
                integrationTask(),
                cliTask(),
+               containersStorageTestTask(),
                qualityTask(),
 
                generateTask(),
@@ -86,12 +97,12 @@
                Description: "run integration tests",
                RunsOn:      lang.List("test"),
                Run: func() {
-                       Run(`go test -v ./test/integration`)
+                       Run(`go test -v -tags=` + buildTags + ` 
./test/integration`)
                        // update database outside race detector, since doing 
so with
                        // race detector on is very slow
                        Run(fmt.Sprintf(`go run ./cmd/%s db update`, project))
                        // exercise most of the CLI with the data race detector 
enabled
-                       Run(fmt.Sprintf(`go run -race ./cmd/%s alpine:latest`, 
project))
+                       Run(fmt.Sprintf(`go run -race -tags=%s ./cmd/%s 
alpine:latest`, buildTags, project))
                },
        }
 }
@@ -127,6 +138,39 @@
        Run(`go run -C .make . snapshot:single-target`)
 }
 
+// containersStorageTestTask builds a fixture image with BUILDER (podman or 
buildah) into an isolated local store and
+// scans it with the linux snapshot binary. Linux only, and not hooked into 
"test" since it needs the builder installed.
+func containersStorageTestTask() Task {
+       return Task{
+               Name:        "containers-storage-test",
+               Description: "run containers-storage tests 
(BUILDER=podman|buildah)",
+               Run: func() {
+                       bin := linuxSnapshotBinPath()
+                       if !file.Exists(bin) {
+                               log.Info("snapshot binary not found at %s; 
building single-target snapshot", bin)
+                               Run(`go run -C .make . build`)
+                       }
+                       Run(
+                               "bash test/containers-storage/source-test.sh 
"+config.Env("BUILDER", "podman"),
+                               run.Env("GRYPE_BINARY_LOCATION", bin),
+                       )
+               },
+       }
+}
+
+// linuxSnapshotBinPath returns the absolute path to the linux snapshot binary 
for the host arch, mirroring
+// goreleaser's <build id>_<goos>_<goarch><microarch level> dist dir naming 
(see test/cli/utils_test.go).
+func linuxSnapshotBinPath() string {
+       arch := runtime.GOARCH
+       switch arch {
+       case "amd64":
+               arch += "_v1"
+       case "arm64":
+               arch += "_v8.0"
+       }
+       return filepath.Join(RootDir(), snapshotBn, "linux-build_linux_"+arch, 
project)
+}
+
 func qualityTask() Task {
        return Task{
                Name:        "quality",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/README.md new/grype-0.120.1/README.md
--- old/grype-0.120.0/README.md 2026-10-02 15:23:52.000000000 +0200
+++ new/grype-0.120.1/README.md 2026-10-06 18:42:08.000000000 +0200
@@ -53,6 +53,19 @@
 grype ./my-project
 ```
 
+### Local containers-storage images
+
+On Linux, grype can scan images from a local containers-storage store (e.g. 
built with Buildah or Podman) when asked explicitly; plain image references 
never look there:
+
+```bash
+grype --from containers-storage localhost/myimage:latest
+
+# rootless stores must be read from inside the builder's user namespace
+podman unshare grype --from containers-storage localhost/myimage:latest
+```
+
+This is included in the Linux release binaries. When building from source, add 
`-tags containers_image_openpgp,exclude_graphdriver_btrfs`.
+
 Scan an SBOM for even faster vulnerability detection:
 
 ```bash
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/cmd/grype/cli/options/grype.go 
new/grype-0.120.1/cmd/grype/cli/options/grype.go
--- old/grype-0.120.0/cmd/grype/cli/options/grype.go    2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/cmd/grype/cli/options/grype.go    2026-10-06 
18:42:08.000000000 +0200
@@ -157,7 +157,7 @@
 
        flags.StringArrayVarP(&o.From,
                "from", "",
-               "specify the source behavior to use (e.g. docker, registry, 
podman, oci-dir, ...)",
+               "specify the source behavior to use (e.g. docker, registry, 
podman, containers-storage, oci-dir, ...)",
        )
 
        flags.StringArrayVarP(&o.VexDocuments,
@@ -181,7 +181,7 @@
 func (o *Grype) DescribeFields(descriptions clio.FieldDescriptionSet) {
        descriptions.Add(&o.CheckForAppUpdate, `enable/disable checking for 
application updates on startup`)
        descriptions.Add(&o.DefaultImagePullSource, `allows users to specify 
which image source should be used to generate the sbom
-valid values are: registry, docker, podman`)
+valid values are: registry, docker, podman, containers-storage`)
        descriptions.Add(&o.Name, `same as --name; set the name of the target 
being analyzed`)
        descriptions.Add(&o.Exclusions, `a list of globs to exclude from 
scanning, for example:
   - '/etc/**'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/go.mod new/grype-0.120.1/go.mod
--- old/grype-0.120.0/go.mod    2026-10-02 15:23:52.000000000 +0200
+++ new/grype-0.120.1/go.mod    2026-10-06 18:42:08.000000000 +0200
@@ -17,7 +17,7 @@
        github.com/anchore/go-logger v0.2.0
        github.com/anchore/go-version v1.2.2-0.20210903204242-51efa5b487c4
        github.com/anchore/packageurl-go v0.2.0
-       github.com/anchore/stereoscope v0.3.3
+       github.com/anchore/stereoscope v0.3.4
        github.com/aquasecurity/go-pep440-version v0.0.1
        github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de
        github.com/bitnami/go-version v0.0.0-20250505154626-452e8c5ee607
@@ -47,7 +47,7 @@
        github.com/iancoleman/strcase v0.3.0
        github.com/invopop/jsonschema v0.14.0
        github.com/jinzhu/copier v0.4.0
-       github.com/klauspost/compress v1.20.0
+       github.com/klauspost/compress v1.20.1
        github.com/knqyf263/go-apk-version v0.0.0-20200609155635-041fdbb8563f
        github.com/knqyf263/go-deb-version v0.0.0-20241115132648-6f4aee6ccd23
        github.com/masahiro331/go-mvn-version v0.0.0-20250131095131-f4974fa13b8a
@@ -78,7 +78,7 @@
 )
 
 require (
-       github.com/anchore/syft v1.54.0
+       github.com/anchore/syft v1.54.1
        github.com/bmatcuk/doublestar/v4 v4.10.2
        github.com/santhosh-tekuri/jsonschema/v6 v6.0.3
 )
@@ -111,7 +111,7 @@
        github.com/agext/levenshtein v1.2.3 // indirect
        github.com/anchore/go-lzo v0.1.1 // indirect
        github.com/anchore/go-macholibre v0.1.1 // indirect
-       github.com/anchore/go-rpmdb v0.2.1 // indirect
+       github.com/anchore/go-rpmdb v0.2.2 // indirect
        github.com/anchore/go-struct-converter v0.2.0-rc2 // indirect
        github.com/anchore/go-sync v0.1.2 // indirect
        github.com/andybalholm/brotli v1.2.0 // indirect
@@ -177,7 +177,7 @@
        github.com/deitch/magic v0.0.0-20240306090643-c67ab88f10cb // indirect
        github.com/diskfs/go-diskfs v1.9.4 // indirect
        github.com/distribution/reference v0.6.0 // indirect
-       github.com/docker/cli v29.8.1+incompatible // indirect
+       github.com/docker/cli v29.8.2+incompatible // indirect
        github.com/docker/docker-credential-helpers v0.9.8 // indirect
        github.com/docker/go-connections v0.8.1 // indirect
        github.com/docker/go-units v0.5.0 // indirect
@@ -291,11 +291,11 @@
        github.com/sagikazarmark/locafero v0.11.0 // indirect
        github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // 
indirect
        github.com/sassoftware/go-rpmutils v0.4.0 // indirect
-       github.com/secure-systems-lab/go-securesystemslib v0.11.0 // indirect
+       github.com/secure-systems-lab/go-securesystemslib v0.11.1 // indirect
        github.com/shopspring/decimal v1.4.0 // indirect
        github.com/sigstore/fulcio v1.8.7 // indirect
-       github.com/sigstore/protobuf-specs v0.5.1 // indirect
-       github.com/sigstore/sigstore v1.10.8 // indirect
+       github.com/sigstore/protobuf-specs v0.5.2 // indirect
+       github.com/sigstore/sigstore v1.10.11 // indirect
        github.com/sirupsen/logrus v1.10.2 // indirect
        github.com/skeema/knownhosts v1.3.1 // indirect
        github.com/smallnest/ringbuffer v0.0.0-20241116012123-461381446e3d // 
indirect
@@ -311,7 +311,7 @@
        github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 
// indirect
        github.com/stretchr/objx v0.5.3 // indirect
        github.com/subosito/gotenv v1.6.0 // indirect
-       github.com/sylabs/sif/v2 v2.24.1 // indirect
+       github.com/sylabs/sif/v2 v2.24.2 // indirect
        github.com/sylabs/squashfs v1.0.6 // indirect
        github.com/tailscale/hujson v0.0.0-20260302212456-ecc657c15afd // 
indirect
        github.com/tchap/go-patricia/v2 v2.3.3 // indirect
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/go.sum new/grype-0.120.1/go.sum
--- old/grype-0.120.0/go.sum    2026-10-02 15:23:52.000000000 +0200
+++ new/grype-0.120.1/go.sum    2026-10-06 18:42:08.000000000 +0200
@@ -146,8 +146,8 @@
 github.com/anchore/go-lzo v0.1.1/go.mod 
h1:3kLx0bve2oN1iDwgM1U5zGku1Tfbdb0No5qp1eL1fIk=
 github.com/anchore/go-macholibre v0.1.1 
h1:sTBHi3S1WVIOCamc6NyT8Sn9mBmD30DCTfjfVm4k6/M=
 github.com/anchore/go-macholibre v0.1.1/go.mod 
h1:YNq2610RlvGCK0Za+Klz/OCMtUaEnwwAGA/VfUAQaro=
-github.com/anchore/go-rpmdb v0.2.1 
h1:BB+8usTkB1ajJ8i1xuzV7TGSTtjqn3/dDi1EuPsxO9w=
-github.com/anchore/go-rpmdb v0.2.1/go.mod 
h1:Y64EbetdqhryMjtk8IzXkdCQw/aNDx+feZCT9aj6rjs=
+github.com/anchore/go-rpmdb v0.2.2 
h1:44VC7mvFAxV9t5JUZYg3S9sqG+E94iZvyWACMDq9hSk=
+github.com/anchore/go-rpmdb v0.2.2/go.mod 
h1:Y64EbetdqhryMjtk8IzXkdCQw/aNDx+feZCT9aj6rjs=
 github.com/anchore/go-struct-converter v0.2.0-rc2 
h1:q+859fW2/jbHJHB2etbNfRlFwYpknyvbqqk1hUdamQ4=
 github.com/anchore/go-struct-converter v0.2.0-rc2/go.mod 
h1:cDBA5vhcR62nXWo8QH9/Kk2807o65ISaHPNPX66L+Uw=
 github.com/anchore/go-sync v0.1.2 
h1:RDD5RCanrWqhbtBulqPSZpERadUlgcYjpybYzYd3Uk8=
@@ -156,10 +156,10 @@
 github.com/anchore/go-version v1.2.2-0.20210903204242-51efa5b487c4/go.mod 
h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E=
 github.com/anchore/packageurl-go v0.2.0 
h1:CkrM4RMUwrEGAiE1OVlxaZNzWj0TuHRey7o4T/EAErk=
 github.com/anchore/packageurl-go v0.2.0/go.mod 
h1:2JCgOQMIsqZ7TmliXG4PnUthPJAKE3mWQbsW2XHjAOE=
-github.com/anchore/stereoscope v0.3.3 
h1:sur8G2THAOnOrSXDjIc1SXzQwco8hjFBtGFq1jFvNVA=
-github.com/anchore/stereoscope v0.3.3/go.mod 
h1:LxL4iOFtB8XMbA1MykUUTkmtQmDuYdbr4+TkBkCfljU=
-github.com/anchore/syft v1.54.0 h1:8JEusKFXXHxezNpYQiUqx7KTpInkW284iGAQMEEqy3k=
-github.com/anchore/syft v1.54.0/go.mod 
h1:wT/lRov8P7XmVNTuyCEgdgIakdLuxYjm+SWXDVvjecs=
+github.com/anchore/stereoscope v0.3.4 
h1:dT5AfjCTXUJowMiRIc+VBQVwvwnIEwnxxwA1GwAkMxw=
+github.com/anchore/stereoscope v0.3.4/go.mod 
h1:+HxqHTt7dvH8mea0mf3ulqkf084VvHiT1grpAQf5uEs=
+github.com/anchore/syft v1.54.1 h1:IdNS5Ha7WfatXHDL0qzjdf7DBVnfb8OI3FpSbltv0nc=
+github.com/anchore/syft v1.54.1/go.mod 
h1:M3Nnl7wN05wWBbffETQ+P3TEhuCDuOUhfTD4tyNX4rA=
 github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod 
h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
 github.com/andybalholm/brotli v1.2.0 
h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
 github.com/andybalholm/brotli v1.2.0/go.mod 
h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
@@ -364,8 +364,8 @@
 github.com/djherbis/times v1.6.0/go.mod 
h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0=
 github.com/dlclark/regexp2 v1.11.0 
h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
 github.com/dlclark/regexp2 v1.11.0/go.mod 
h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
-github.com/docker/cli v29.8.1+incompatible 
h1:qYL1bCp6cRw2SB1xmLlIOPyV171dilw9W2Jew38vy9c=
-github.com/docker/cli v29.8.1+incompatible/go.mod 
h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
+github.com/docker/cli v29.8.2+incompatible 
h1:2zgdFuoFst2T80oS42vhKGxkd0JRo305eIEKTsxR7pQ=
+github.com/docker/cli v29.8.2+incompatible/go.mod 
h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
 github.com/docker/distribution v2.8.3+incompatible 
h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
 github.com/docker/distribution v2.8.3+incompatible/go.mod 
h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
 github.com/docker/docker v28.5.2+incompatible 
h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM=
@@ -695,8 +695,8 @@
 github.com/kisielk/errcheck v1.5.0/go.mod 
h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/gotool v1.0.0/go.mod 
h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 github.com/klauspost/compress v1.4.1/go.mod 
h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
-github.com/klauspost/compress v1.20.0 
h1:a3C1ke2ohxFymNlb2HWAHjDeKCI90scRskErZkR0ezA=
-github.com/klauspost/compress v1.20.0/go.mod 
h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI=
+github.com/klauspost/compress v1.20.1 
h1:T7kKElXUMXrUJ2E9QhQhxFtcK5rPyLdsGZvdbLMPdiQ=
+github.com/klauspost/compress v1.20.1/go.mod 
h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI=
 github.com/klauspost/cpuid v1.2.0/go.mod 
h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
 github.com/klauspost/cpuid/v2 v2.3.0 
h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
 github.com/klauspost/cpuid/v2 v2.3.0/go.mod 
h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
@@ -942,8 +942,8 @@
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod 
h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
 github.com/sebdah/goldie/v2 v2.8.0 
h1:dZb9wR8q5++oplmEiJT+U/5KyotVD+HNGCAc5gNr8rc=
 github.com/sebdah/goldie/v2 v2.8.0/go.mod 
h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
-github.com/secure-systems-lab/go-securesystemslib v0.11.0 
h1:iuCR9kcMFD4QurdKrGvPLoKZLv9YvwPYVr0473BdtFs=
-github.com/secure-systems-lab/go-securesystemslib v0.11.0/go.mod 
h1:+PMOTjUGwHj2vcZ+TFKlb1tXRbrdWE1LYDT5i9JC80Q=
+github.com/secure-systems-lab/go-securesystemslib v0.11.1 
h1:ayahDPjfSIqKegyt5YVGEvQ7SAi72GHXTy+b2YjUd5w=
+github.com/secure-systems-lab/go-securesystemslib v0.11.1/go.mod 
h1:UyOjhoZLi76ir63u1ptubEevVe6dlNPmNxwgVvKqFFY=
 github.com/sergi/go-diff v1.1.0/go.mod 
h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
 github.com/sergi/go-diff v1.2.0/go.mod 
h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
 github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
@@ -953,10 +953,10 @@
 github.com/shopspring/decimal v1.4.0/go.mod 
h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
 github.com/sigstore/fulcio v1.8.7 
h1:d7QJQxukgXarqPCT9uDNeyzt1Bbt/biw58/VfOnwI/o=
 github.com/sigstore/fulcio v1.8.7/go.mod 
h1:7fX+QyigZxRGKTgHvTfOfxwwniCDxK02PVloHy5/vg4=
-github.com/sigstore/protobuf-specs v0.5.1 
h1:/5OPaNuolRJmQfeZLayJGFXMpsRJEdgC6ah1/+7Px7U=
-github.com/sigstore/protobuf-specs v0.5.1/go.mod 
h1:DRBzpFuE+LnvQMN10/dU6nBeKwVLGEQ6o2FovN2Rats=
-github.com/sigstore/sigstore v1.10.8 
h1:1Mgkxvkw4AXMfIP1DOjc6kw0GkUgA8pGVpveN/EfOq4=
-github.com/sigstore/sigstore v1.10.8/go.mod 
h1:f9+B/4iaYimvUkySyb2mvc73n3RLqNn24grHZM/ET8M=
+github.com/sigstore/protobuf-specs v0.5.2 
h1:RSWWUY8QrVTxbYH00jY/jg2e7YnjzrpwP+PeHTMll0E=
+github.com/sigstore/protobuf-specs v0.5.2/go.mod 
h1:DRBzpFuE+LnvQMN10/dU6nBeKwVLGEQ6o2FovN2Rats=
+github.com/sigstore/sigstore v1.10.11 
h1:fjrwDfR0AWmRONYV/hKGJyqbT0osMtaBz9FTZ6MH9XI=
+github.com/sigstore/sigstore v1.10.11/go.mod 
h1:ecPk+ftLqP8/TmzQFJmn0+QrL2yUQIJvyzVKNmDiw6U=
 github.com/sirupsen/logrus v1.2.0/go.mod 
h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/sirupsen/logrus v1.4.2/go.mod 
h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
 github.com/sirupsen/logrus v1.7.0/go.mod 
h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
@@ -1020,8 +1020,8 @@
 github.com/subosito/gotenv v1.2.0/go.mod 
h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
 github.com/subosito/gotenv v1.6.0 
h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
 github.com/subosito/gotenv v1.6.0/go.mod 
h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
-github.com/sylabs/sif/v2 v2.24.1 
h1:OhTOfTwBaGXfbWYWXK9C6Pojma3A1bTaNJ6CEhyuKok=
-github.com/sylabs/sif/v2 v2.24.1/go.mod 
h1:PRq9MoP0g+p0qE5ZRGrOhyVAUdHrPsAVmXHgoiW6VU0=
+github.com/sylabs/sif/v2 v2.24.2 
h1:rdkFf6z3xLC6yKweU7S9marlKfkS91Ht0ruIri6YWFY=
+github.com/sylabs/sif/v2 v2.24.2/go.mod 
h1:bbrkk0JhTX+xNJcnUtmDkivoO2r4DGWM3LxNR0U2ooA=
 github.com/sylabs/squashfs v1.0.6 
h1:PvJcDzxr+vIm2kH56mEMbaOzvGu79gK7P7IX+R7BDZI=
 github.com/sylabs/squashfs v1.0.6/go.mod 
h1:DlDeUawVXLWAsSRa085Eo0ZenGzAB32JdAUFaB0LZfE=
 github.com/tailscale/hujson v0.0.0-20260302212456-ecc657c15afd 
h1:Rf9uhF1+VJ7ZHqxrG8pJ6YacmHvVCmByDmGbAWCc/gA=
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/grype/db/build.go 
new/grype-0.120.1/grype/db/build.go
--- old/grype-0.120.0/grype/db/build.go 2026-10-02 15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/db/build.go 2026-10-06 18:42:08.000000000 +0200
@@ -161,6 +161,7 @@
                                return fmt.Errorf("failed to open cache entry 
%q: %w", opener.String(), err)
                        }
                        envelope, err := unmarshal.Envelope(f)
+                       _ = f.Close()
                        if err != nil {
                                return fmt.Errorf("failed to unmarshal cache 
entry %q: %w", opener.String(), err)
                        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/grype/db/internal/gormadapter/open.go 
new/grype-0.120.1/grype/db/internal/gormadapter/open.go
--- old/grype-0.120.0/grype/db/internal/gormadapter/open.go     2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/db/internal/gormadapter/open.go     2026-10-06 
18:42:08.000000000 +0200
@@ -147,7 +147,15 @@
                return nil, fmt.Errorf("unable to connect to DB: %w", err)
        }
 
-       return cfg.prepareDB(dbObj)
+       prepared, err := cfg.prepareDB(dbObj)
+       if err != nil {
+               // don't leave the file handle open (this blocks removing the 
file on windows)
+               if d, dbErr := dbObj.DB(); dbErr == nil {
+                       _ = d.Close()
+               }
+               return nil, err
+       }
+       return prepared, nil
 }
 
 func (c config) prepareDB(dbObj *gorm.DB) (*gorm.DB, error) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/grype-0.120.0/grype/db/internal/gormadapter/open_test.go 
new/grype-0.120.1/grype/db/internal/gormadapter/open_test.go
--- old/grype-0.120.0/grype/db/internal/gormadapter/open_test.go        
2026-10-02 15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/db/internal/gormadapter/open_test.go        
2026-10-06 18:42:08.000000000 +0200
@@ -3,6 +3,7 @@
 import (
        "os"
        "path/filepath"
+       "runtime"
        "testing"
 
        "github.com/stretchr/testify/require"
@@ -107,8 +108,9 @@
                tempDir := t.TempDir()
                dbPath := filepath.Join(tempDir, "test.db")
 
-               _, err := os.Create(dbPath)
+               f, err := os.Create(dbPath)
                require.NoError(t, err)
+               require.NoError(t, f.Close())
 
                _, err = os.Stat(dbPath)
                require.NoError(t, err)
@@ -121,6 +123,9 @@
        })
 
        t.Run("returns error if unable to create parent directory", func(t 
*testing.T) {
+               if runtime.GOOS == "windows" {
+                       t.Skip("relies on posix permissions under /root")
+               }
                invalidDir := filepath.Join("/root", "invalidDir", "test.db")
                err := deleteDB(invalidDir)
                require.Error(t, err)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/grype-0.120.0/grype/db/internal/tarutil/populate_test.go 
new/grype-0.120.1/grype/db/internal/tarutil/populate_test.go
--- old/grype-0.120.0/grype/db/internal/tarutil/populate_test.go        
2026-10-02 15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/db/internal/tarutil/populate_test.go        
2026-10-06 18:42:08.000000000 +0200
@@ -44,6 +44,7 @@
                        require.NoError(t, err)
                        _, err = f.Write([]byte("hello world\n"))
                        require.NoError(t, err)
+                       require.NoError(t, f.Close())
                        archivePath := filepath.Join(dir, tt.tarPath)
                        err = PopulateWithPaths(archivePath, tempPath)
                        require.NoError(t, err)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/grype/db/internal/tarutil/writer.go 
new/grype-0.120.1/grype/db/internal/tarutil/writer.go
--- old/grype-0.120.0/grype/db/internal/tarutil/writer.go       2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/db/internal/tarutil/writer.go       2026-10-06 
18:42:08.000000000 +0200
@@ -51,6 +51,33 @@
                return nil, err
        }
 
+       c, err := newCompressor(archivePath, archive, compressorCommands)
+       if err != nil {
+               _ = archive.Close()
+               return nil, err
+       }
+       if c == io.WriteCloser(archive) {
+               return c, nil
+       }
+       // compressors don't own the underlying file, so close it after the 
compressor has flushed
+       return &archiveCompressor{WriteCloser: c, archive: archive}, nil
+}
+
+// archiveCompressor closes the archive file after closing the compressor 
writing to it.
+type archiveCompressor struct {
+       io.WriteCloser
+       archive *os.File
+}
+
+func (a *archiveCompressor) Close() error {
+       err := a.WriteCloser.Close()
+       if closeErr := a.archive.Close(); closeErr != nil && err == nil {
+               err = closeErr
+       }
+       return err
+}
+
+func newCompressor(archivePath string, archive *os.File, compressorCommands 
map[string]string) (io.WriteCloser, error) {
        // check for custom compressor command first
        for ext, cmd := range compressorCommands {
                if strings.HasSuffix(archivePath, "."+ext) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/grype-0.120.0/grype/db/internal/tarutil/writer_test.go 
new/grype-0.120.1/grype/db/internal/tarutil/writer_test.go
--- old/grype-0.120.0/grype/db/internal/tarutil/writer_test.go  2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/db/internal/tarutil/writer_test.go  2026-10-06 
18:42:08.000000000 +0200
@@ -45,7 +45,7 @@
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
                        dir := t.TempDir()
-                       require.NoError(t, os.Chdir(dir))
+                       t.Chdir(dir)
                        testFilePath := "testfile"
                        testString := "hello world"
                        require.NoError(t, os.WriteFile(testFilePath, 
[]byte(testString), 0644))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/grype/db/provider/entry/sqlite.go 
new/grype-0.120.1/grype/db/provider/entry/sqlite.go
--- old/grype-0.120.0/grype/db/provider/entry/sqlite.go 2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/db/provider/entry/sqlite.go 2026-10-06 
18:42:08.000000000 +0200
@@ -41,6 +41,7 @@
        if err != nil {
                return nil, err
        }
+       defer closeDB(db)
 
        query := db.Model(&results{})
 
@@ -93,6 +94,7 @@
        if err != nil {
                return 0, err
        }
+       defer closeDB(db)
 
        var count int64
        db.Model(&results{}).Count(&count)
@@ -124,6 +126,7 @@
        openers := make(chan Opener)
        go func() {
                defer close(openers)
+               defer closeDB(db)
 
                var models []results
 
@@ -187,6 +190,12 @@
        return dbObj, nil
 }
 
+func closeDB(db *gorm.DB) {
+       if d, err := db.DB(); err == nil {
+               _ = d.Close()
+       }
+}
+
 // ConnectionString creates a connection string for sqlite3
 func connectionString(path string) (string, error) {
        if path == "" {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/grype/db/provider/state.go 
new/grype-0.120.1/grype/db/provider/state.go
--- old/grype-0.120.0/grype/db/provider/state.go        2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/db/provider/state.go        2026-10-06 
18:42:08.000000000 +0200
@@ -72,6 +72,7 @@
                if err != nil {
                        return nil, fmt.Errorf("unable to open listing file %q: 
%w", listingPath, err)
                }
+               defer f.Close()
 
                // note: bufio scanner is **much** faster than Fscan
                scanner := bufio.NewScanner(f)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/grype/db/provider/workspace.go 
new/grype-0.120.1/grype/db/provider/workspace.go
--- old/grype-0.120.0/grype/db/provider/workspace.go    2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/db/provider/workspace.go    2026-10-06 
18:42:08.000000000 +0200
@@ -121,7 +121,7 @@
 
                // format: <hash>  results/<relative-path>
                // the path is relative to the provider directory
-               listingPath := filepath.Join("results", relPath)
+               listingPath := filepath.ToSlash(filepath.Join("results", 
relPath))
                if _, err := fmt.Fprintf(writer, "%s  %s\n", hash, 
listingPath); err != nil {
                        return err
                }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/grype/db/provider/workspace_writer.go 
new/grype-0.120.1/grype/db/provider/workspace_writer.go
--- old/grype-0.120.0/grype/db/provider/workspace_writer.go     2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/db/provider/workspace_writer.go     2026-10-06 
18:42:08.000000000 +0200
@@ -116,7 +116,7 @@
        _, _ = hasher.Write(formattedContent)
 
        return &File{
-               Path:      filepath.Join("results", filename),
+               Path:      filepath.ToSlash(filepath.Join("results", filename)),
                Digest:    hex.EncodeToString(hasher.Sum(nil)),
                Algorithm: xxh64Algorithm,
        }, nil
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/grype/db/v5/distribution/curator.go 
new/grype-0.120.1/grype/db/v5/distribution/curator.go
--- old/grype-0.120.0/grype/db/v5/distribution/curator.go       2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/db/v5/distribution/curator.go       2026-10-06 
18:42:08.000000000 +0200
@@ -542,6 +542,7 @@
        if err != nil {
                return err
        }
+       defer root.Close()
 
        visitor := func(_ context.Context, file archives.FileInfo) error {
                if file.IsDir() || file.LinkTarget != "" {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/grype-0.120.0/grype/db/v5/distribution/curator_test.go 
new/grype-0.120.1/grype/db/v5/distribution/curator_test.go
--- old/grype-0.120.0/grype/db/v5/distribution/curator_test.go  2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/db/v5/distribution/curator_test.go  2026-10-06 
18:42:08.000000000 +0200
@@ -789,6 +789,7 @@
        }
        err = format.Archive(t.Context(), out, files)
        require.NoError(t, err)
+       require.NoError(t, out.Close())
 
        destination := t.TempDir()
        err = unarchive(source, destination)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/grype-0.120.0/grype/db/v5/distribution/metadata_test.go 
new/grype-0.120.1/grype/db/v5/distribution/metadata_test.go
--- old/grype-0.120.0/grype/db/v5/distribution/metadata_test.go 2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/db/v5/distribution/metadata_test.go 2026-10-06 
18:42:08.000000000 +0200
@@ -1,6 +1,7 @@
 package distribution
 
 import (
+       "runtime"
        "testing"
        "time"
 
@@ -38,6 +39,9 @@
 
        for _, test := range tests {
                t.Run(test.fixture, func(t *testing.T) {
+                       if test.err && runtime.GOOS == "windows" {
+                               t.Skip("relies on posix ENOTDIR semantics, 
windows reports the path as not existing")
+                       }
                        metadata, err := NewMetadataFromDir(afero.NewOsFs(), 
test.fixture)
                        if err != nil && !test.err {
                                t.Fatalf("failed to get metadata: %+v", err)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/grype/db/v5/store/diff_test.go 
new/grype-0.120.1/grype/db/v5/store/diff_test.go
--- old/grype-0.120.0/grype/db/v5/store/diff_test.go    2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/db/v5/store/diff_test.go    2026-10-06 
18:42:08.000000000 +0200
@@ -18,6 +18,7 @@
        if err != nil {
                t.Fatalf("could not create store: %+v", err)
        }
+       closeOnCleanup(t, s)
 
        //WHEN
        result, err := s.GetAllVulnerabilities()
@@ -37,6 +38,7 @@
        if err != nil {
                t.Fatalf("could not create store: %+v", err)
        }
+       closeOnCleanup(t, s)
 
        //WHEN
        result, err := s.GetAllVulnerabilityMetadata()
@@ -54,12 +56,14 @@
        if err != nil {
                t.Fatalf("could not create store: %+v", err)
        }
+       closeOnCleanup(t, s1)
        dbTempFile = t.TempDir()
 
        s2, err := New(dbTempFile, true)
        if err != nil {
                t.Fatalf("could not create store: %+v", err)
        }
+       closeOnCleanup(t, s2)
 
        baseVulns := []v5.Vulnerability{
                {
@@ -159,11 +163,13 @@
        if err != nil {
                t.Fatalf("could not create store: %+v", err)
        }
+       closeOnCleanup(t, s1)
        dbTempFile = t.TempDir()
        s2, err := New(dbTempFile, true)
        if err != nil {
                t.Fatalf("could not create store: %+v", err)
        }
+       closeOnCleanup(t, s2)
 
        baseVulns := []v5.VulnerabilityMetadata{
                {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/grype/db/v5/store/store_test.go 
new/grype-0.120.1/grype/db/v5/store/store_test.go
--- old/grype-0.120.0/grype/db/v5/store/store_test.go   2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/db/v5/store/store_test.go   2026-10-06 
18:42:08.000000000 +0200
@@ -27,6 +27,15 @@
        }
 }
 
+// closeOnCleanup closes the underlying sqlite handle so the temp dir can be 
removed (open files can't be deleted on windows)
+func closeOnCleanup(t *testing.T, s v5.Store) {
+       t.Cleanup(func() {
+               if d, err := s.(*store).db.DB(); err == nil {
+                       _ = d.Close()
+               }
+       })
+}
+
 func TestStore_GetID_SetID(t *testing.T) {
        dbTempFile := t.TempDir()
 
@@ -34,6 +43,7 @@
        if err != nil {
                t.Fatalf("could not create store: %+v", err)
        }
+       closeOnCleanup(t, s)
 
        expected := v5.ID{
                BuildTimestamp: time.Now().UTC(),
@@ -72,6 +82,7 @@
        if err != nil {
                t.Fatalf("could not create store: %+v", err)
        }
+       closeOnCleanup(t, s)
 
        extra := []v5.Vulnerability{
                {
@@ -275,6 +286,7 @@
        if err != nil {
                t.Fatalf("could not create store: %+v", err)
        }
+       closeOnCleanup(t, s)
 
        total := []v5.VulnerabilityMetadata{
                {
@@ -745,6 +757,7 @@
                        if err != nil {
                                t.Fatalf("could not create store: %+v", err)
                        }
+                       closeOnCleanup(t, s)
 
                        // add each metadata in order
                        var theErr error
@@ -1014,6 +1027,7 @@
                        if err != nil {
                                t.Fatalf("could not create s: %+v", err)
                        }
+                       closeOnCleanup(t, s)
 
                        // add each metadata in order
                        for _, metadata := range test.add {
@@ -1061,6 +1075,7 @@
        if err != nil {
                t.Fatalf("could not create store: %+v", err)
        }
+       closeOnCleanup(t, s)
 
        extra := []v5.VulnerabilityMatchExclusion{
                {
@@ -1217,11 +1232,13 @@
        if err != nil {
                t.Fatalf("could not create store: %+v", err)
        }
+       closeOnCleanup(t, s1)
        dbTempFile = t.TempDir()
        s2, err := New(dbTempFile, true)
        if err != nil {
                t.Fatalf("could not create store: %+v", err)
        }
+       closeOnCleanup(t, s2)
 
        baseVulns := []v5.Vulnerability{
                {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/grype-0.120.0/grype/db/v6/build/transformers/openvex/transform_test.go 
new/grype-0.120.1/grype/db/v6/build/transformers/openvex/transform_test.go
--- old/grype-0.120.0/grype/db/v6/build/transformers/openvex/transform_test.go  
2026-10-02 15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/db/v6/build/transformers/openvex/transform_test.go  
2026-10-06 18:42:08.000000000 +0200
@@ -8,13 +8,12 @@
        govex "github.com/openvex/go-vex/pkg/vex"
        "github.com/stretchr/testify/require"
 
-       "github.com/anchore/packageurl-go"
-
        "github.com/anchore/grype/grype/db/internal/provider/unmarshal"
        "github.com/anchore/grype/grype/db/provider"
        db "github.com/anchore/grype/grype/db/v6"
        "github.com/anchore/grype/grype/db/v6/build/transformers"
        "github.com/anchore/grype/grype/db/v6/build/transformers/internal"
+       "github.com/anchore/packageurl-go"
 )
 
 var timeVal = time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/grype/db/v6/db_metadata_store_test.go 
new/grype-0.120.1/grype/db/v6/db_metadata_store_test.go
--- old/grype-0.120.0/grype/db/v6/db_metadata_store_test.go     2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/db/v6/db_metadata_store_test.go     2026-10-06 
18:42:08.000000000 +0200
@@ -71,6 +71,7 @@
                DBDirPath: dir,
        }, true, true)
        require.NoError(t, err)
+       closeOnCleanup(t, s)
 
        require.NoError(t, s.SetDBMetadata())
 
@@ -82,6 +83,17 @@
                DBDirPath: dir,
        }, false, false)
        require.NoError(t, err)
+       closeOnCleanup(t, s)
 
        return s
 }
+
+// closeOnCleanup closes the underlying connection when the test ends (without 
the vacuum/index work that
+// store.Close does), since windows cannot remove the temp dir while the db 
file is still open.
+func closeOnCleanup(t testing.TB, s *store) {
+       t.Cleanup(func() {
+               if d, err := s.db.DB(); err == nil {
+                       _ = d.Close()
+               }
+       })
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/grype/db/v6/diff/db_resolver.go 
new/grype-0.120.1/grype/db/v6/diff/db_resolver.go
--- old/grype-0.120.0/grype/db/v6/diff/db_resolver.go   2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/db/v6/diff/db_resolver.go   2026-10-06 
18:42:08.000000000 +0200
@@ -156,6 +156,7 @@
        if err != nil {
                return err
        }
+       defer log.CloseAndLogError(root, destination)
 
        visitor := func(_ context.Context, file archives.FileInfo) error {
                if file.IsDir() || file.LinkTarget != "" {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/grype/db/v6/diff/differ.go 
new/grype-0.120.1/grype/db/v6/diff/differ.go
--- old/grype-0.120.0/grype/db/v6/diff/differ.go        2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/db/v6/diff/differ.go        2026-10-06 
18:42:08.000000000 +0200
@@ -68,10 +68,12 @@
 
        beforeTime, err := time.Parse(time.RFC3339, oldDB.Info.BuildTimestamp)
        if err != nil {
+               closeLowLevelDB(db)
                return nil, fmt.Errorf("failed to parse build timestamp: %w", 
err)
        }
        afterTime, err := time.Parse(time.RFC3339, newDB.Info.BuildTimestamp)
        if err != nil {
+               closeLowLevelDB(db)
                return nil, fmt.Errorf("failed to parse build timestamp: %w", 
err)
        }
 
@@ -94,10 +96,11 @@
 
 // Close detaches the new database and closes the connection.
 func (d *DBDiffer) Close() error {
+       // always release the connection, even if the detach fails (an open 
handle keeps the db files locked on windows)
+       defer closeLowLevelDB(d.db)
        if err := d.db.Exec("DETACH DATABASE new_db").Error; err != nil {
                return fmt.Errorf("failed to detach new database: %w", err)
        }
-       closeLowLevelDB(d.db)
        return nil
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/grype/db/v6/diff/differ_test.go 
new/grype-0.120.1/grype/db/v6/diff/differ_test.go
--- old/grype-0.120.0/grype/db/v6/diff/differ_test.go   2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/db/v6/diff/differ_test.go   2026-10-06 
18:42:08.000000000 +0200
@@ -275,6 +275,7 @@
                                NewDB:  newDB,
                        })
                        require.NoError(t, err)
+                       t.Cleanup(func() { _ = differ.Close() })
                        require.NotNil(t, differ)
 
                        packageResult, err := differ.Diff()
@@ -887,6 +888,7 @@
                                NewDB:  newDB,
                        })
                        require.NoError(t, err)
+                       t.Cleanup(func() { _ = differ.Close() })
                        require.NotNil(t, differ)
 
                        packageResult, err := differ.Diff()
@@ -1097,6 +1099,7 @@
                                NewDB:  newDBDir,
                        })
                        require.NoError(t, err)
+                       t.Cleanup(func() { _ = differ.Close() })
                        require.NotNil(t, differ)
 
                        packageResult, err := differ.Diff()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/grype/db/v6/diff/vuln_diff_test.go 
new/grype-0.120.1/grype/db/v6/diff/vuln_diff_test.go
--- old/grype-0.120.0/grype/db/v6/diff/vuln_diff_test.go        2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/db/v6/diff/vuln_diff_test.go        2026-10-06 
18:42:08.000000000 +0200
@@ -363,6 +363,7 @@
                                EPSSThreshold: epssThreshold,
                        })
                        require.NoError(t, err)
+                       t.Cleanup(func() { _ = differ.Close() })
                        require.NotNil(t, differ)
 
                        result, err := differ.Diff()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/grype-0.120.0/grype/db/v6/distribution/latest_test.go 
new/grype-0.120.1/grype/db/v6/distribution/latest_test.go
--- old/grype-0.120.0/grype/db/v6/distribution/latest_test.go   2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/db/v6/distribution/latest_test.go   2026-10-06 
18:42:08.000000000 +0200
@@ -271,6 +271,7 @@
                        require.NoError(t, err)
                        _, err = tempFile.WriteString(tt.contents)
                        require.NoError(t, err)
+                       require.NoError(t, tempFile.Close())
 
                        archive, err := NewArchive(tempFile.Name(), tt.time, 
tt.model, tt.revision, tt.addition)
                        tt.expectErr(t, err)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/grype/db/v6/import_metadata_test.go 
new/grype-0.120.1/grype/db/v6/import_metadata_test.go
--- old/grype-0.120.0/grype/db/v6/import_metadata_test.go       2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/db/v6/import_metadata_test.go       2026-10-06 
18:42:08.000000000 +0200
@@ -62,8 +62,7 @@
                                err := os.WriteFile(filePath, 
[]byte(tt.fileContent), 0644)
                                require.NoError(t, err)
                        } else if tt.emptyFile {
-                               _, err := os.Create(filePath)
-                               require.NoError(t, err)
+                               require.NoError(t, os.WriteFile(filePath, nil, 
0644))
                        }
 
                        result, err := ReadImportMetadata(afero.NewOsFs(), dir)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/grype/db/v6/installation/curator.go 
new/grype-0.120.1/grype/db/v6/installation/curator.go
--- old/grype-0.120.0/grype/db/v6/installation/curator.go       2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/db/v6/installation/curator.go       2026-10-06 
18:42:08.000000000 +0200
@@ -102,6 +102,7 @@
 
        m, err := s.GetDBMetadata()
        if err != nil {
+               log.CloseAndLogError(s, c.config.DBDirectoryPath())
                return nil, fmt.Errorf("unable to get vulnerability store 
metadata: %w", err)
        }
 
@@ -113,6 +114,7 @@
 
        doRehydrate, err := isRehydrationNeeded(c.fs, 
c.config.DBDirectoryPath(), currentDBSchemaVersion, 
schemaver.New(db.ModelVersion, db.Revision, db.Addition))
        if err != nil {
+               log.CloseAndLogError(s, c.config.DBDirectoryPath())
                return nil, err
        }
        if doRehydrate {
@@ -643,6 +645,7 @@
        if err != nil {
                return err
        }
+       defer root.Close()
 
        visitor := func(_ context.Context, file archives.FileInfo) error {
                if file.IsDir() || file.LinkTarget != "" {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/grype-0.120.0/grype/db/v6/installation/curator_test.go 
new/grype-0.120.1/grype/db/v6/installation/curator_test.go
--- old/grype-0.120.0/grype/db/v6/installation/curator_test.go  2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/db/v6/installation/curator_test.go  2026-10-06 
18:42:08.000000000 +0200
@@ -138,6 +138,11 @@
 
        require.NoError(t, d.Exec("VACUUM").Error)
 
+       // release the file before hashing it (and so the temp dir can be 
removed on windows)
+       sqlDB, err := d.DB()
+       require.NoError(t, err)
+       require.NoError(t, sqlDB.Close())
+
        digest, err := db.CalculateDBDigest(afero.NewOsFs(), c.DBFilePath())
        require.NoError(t, err)
 
@@ -523,6 +528,7 @@
 
                m, err := s.GetDBMetadata()
                require.NoError(t, err)
+               require.NoError(t, s.Close())
 
                return ci.(curator), db.DescriptionFromMetadata(m)
        }
@@ -937,6 +943,7 @@
        }
        err = format.Archive(t.Context(), out, files)
        require.NoError(t, err)
+       require.NoError(t, out.Close())
 
        destination := t.TempDir()
        err = unarchive(source, destination)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/grype-0.120.0/grype/matcher/golang/testdata/gobin-httpclient/Makefile 
new/grype-0.120.1/grype/matcher/golang/testdata/gobin-httpclient/Makefile
--- old/grype-0.120.0/grype/matcher/golang/testdata/gobin-httpclient/Makefile   
2026-10-02 15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/matcher/golang/testdata/gobin-httpclient/Makefile   
2026-10-06 18:42:08.000000000 +0200
@@ -1,8 +1,12 @@
 BINARY := binary
 .DEFAULT_GOAL := $(BINARY)
 
+# always build an ELF binary: syft only extracts go symbols from ELF and 
Mach-O (not PE), so a
+# native windows build would carry no symbols
+export GOOS := linux
+
 .PHONY: clean
-$(BINARY): $(wildcard *.go) go.mod
+$(BINARY): $(wildcard *.go) Makefile go.mod
        go build -trimpath -o $(BINARY) .
 
 clean:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/grype-0.120.0/grype/matcher/golang/testdata/gobin-httpserver/Makefile 
new/grype-0.120.1/grype/matcher/golang/testdata/gobin-httpserver/Makefile
--- old/grype-0.120.0/grype/matcher/golang/testdata/gobin-httpserver/Makefile   
2026-10-02 15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/matcher/golang/testdata/gobin-httpserver/Makefile   
2026-10-06 18:42:08.000000000 +0200
@@ -1,8 +1,12 @@
 BINARY := binary
 .DEFAULT_GOAL := $(BINARY)
 
+# always build an ELF binary: syft only extracts go symbols from ELF and 
Mach-O (not PE), so a
+# native windows build would carry no symbols
+export GOOS := linux
+
 .PHONY: clean
-$(BINARY): $(wildcard *.go) go.mod
+$(BINARY): $(wildcard *.go) Makefile go.mod
        go build -trimpath -o $(BINARY) .
 
 clean:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/grype-0.120.0/grype/matcher/golang/testdata/gobin-xnet-html/Makefile 
new/grype-0.120.1/grype/matcher/golang/testdata/gobin-xnet-html/Makefile
--- old/grype-0.120.0/grype/matcher/golang/testdata/gobin-xnet-html/Makefile    
2026-10-02 15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/matcher/golang/testdata/gobin-xnet-html/Makefile    
2026-10-06 18:42:08.000000000 +0200
@@ -1,8 +1,12 @@
 BINARY := binary
 .DEFAULT_GOAL := $(BINARY)
 
+# always build an ELF binary: syft only extracts go symbols from ELF and 
Mach-O (not PE), so a
+# native windows build would carry no symbols
+export GOOS := linux
+
 .PHONY: clean
-$(BINARY): $(wildcard *.go) go.mod go.sum
+$(BINARY): $(wildcard *.go) Makefile go.mod go.sum
        go build -trimpath -o $(BINARY) .
 
 clean:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/grype-0.120.0/grype/matcher/golang/testdata/gobin-xnet-http2server/Makefile 
new/grype-0.120.1/grype/matcher/golang/testdata/gobin-xnet-http2server/Makefile
--- 
old/grype-0.120.0/grype/matcher/golang/testdata/gobin-xnet-http2server/Makefile 
    2026-10-02 15:23:52.000000000 +0200
+++ 
new/grype-0.120.1/grype/matcher/golang/testdata/gobin-xnet-http2server/Makefile 
    2026-10-06 18:42:08.000000000 +0200
@@ -1,8 +1,12 @@
 BINARY := binary
 .DEFAULT_GOAL := $(BINARY)
 
+# always build an ELF binary: syft only extracts go symbols from ELF and 
Mach-O (not PE), so a
+# native windows build would carry no symbols
+export GOOS := linux
+
 .PHONY: clean
-$(BINARY): $(wildcard *.go) go.mod go.sum
+$(BINARY): $(wildcard *.go) Makefile go.mod go.sum
        go build -trimpath -o $(BINARY) .
 
 clean:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/grype/pkg/provider_test.go 
new/grype-0.120.1/grype/pkg/provider_test.go
--- old/grype-0.120.0/grype/pkg/provider_test.go        2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/pkg/provider_test.go        2026-10-06 
18:42:08.000000000 +0200
@@ -2,6 +2,7 @@
 
 import (
        "os"
+       "runtime"
        "testing"
 
        "github.com/google/go-cmp/cmp"
@@ -134,6 +135,10 @@
 }
 
 func TestSyftLocationExcludes(t *testing.T) {
+       if runtime.GOOS == "windows" {
+               // the docker image fixtures are linux images (FROM scratch), 
which windows docker cannot build
+               t.Skip("linux docker image fixtures are not supported on 
windows")
+       }
        tests := []struct {
                name     string
                fixture  string
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/grype-0.120.0/grype/presenter/internal/test_helpers.go 
new/grype-0.120.1/grype/presenter/internal/test_helpers.go
--- old/grype-0.120.0/grype/presenter/internal/test_helpers.go  2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/presenter/internal/test_helpers.go  2026-10-06 
18:42:08.000000000 +0200
@@ -113,8 +113,10 @@
        cycloneDxBomRefPattern := 
regexp.MustCompile(`[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}`)
        tempDirPattern := regexp.MustCompile(`/tmp/[^"]+`)
        macTempDirPattern := regexp.MustCompile(`/var/folders/[^"]+`)
+       // json-escaped windows paths (e.g. "C:\\Users\\...\\Temp\\...")
+       windowsTempDirPattern := regexp.MustCompile(`[A-Za-z]:\\\\[^"]+`)
 
-       for _, pattern := range []*regexp.Regexp{serialPattern, rfc3339Pattern, 
refPattern, uuidPattern, cycloneDxBomRefPattern, tempDirPattern, 
macTempDirPattern} {
+       for _, pattern := range []*regexp.Regexp{serialPattern, rfc3339Pattern, 
refPattern, uuidPattern, cycloneDxBomRefPattern, tempDirPattern, 
macTempDirPattern, windowsTempDirPattern} {
                s = pattern.ReplaceAll(s, []byte(""))
        }
        return s
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/grype/presenter/sarif/presenter.go 
new/grype-0.120.1/grype/presenter/sarif/presenter.go
--- old/grype-0.120.0/grype/presenter/sarif/presenter.go        2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/presenter/sarif/presenter.go        2026-10-06 
18:42:08.000000000 +0200
@@ -5,7 +5,7 @@
        "fmt"
        "hash"
        "io"
-       "path/filepath"
+       "path"
        "regexp"
        "strings"
 
@@ -194,20 +194,20 @@
 
 // locationPath returns a path for the location, relative to the cwd
 func (p Presenter) locationPath(l file.Location) string {
-       path := l.Path()
+       loc := strings.TrimPrefix(l.Path(), "./")
        in := p.inputPath()
-       path = strings.TrimPrefix(path, "./")
        // trimmed off any ./ and accounted for dir:. for both path and input 
path
        _, ok := p.src.Metadata.(source.DirectoryMetadata)
        if ok {
-               if filepath.IsAbs(path) || in == "" {
-                       return path
+               // location paths are always posix (regardless of host OS), so 
use path over filepath here
+               if path.IsAbs(loc) || in == "" {
+                       return loc
                }
                // return a path relative to the cwd, if it's not absolute
-               return fmt.Sprintf("%s/%s", in, path)
+               return fmt.Sprintf("%s/%s", in, loc)
        }
 
-       return path
+       return loc
 }
 
 // locations the locations array is a single "physical" location with 
potentially multiple logical locations
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/grype/presenter/table/presenter.go 
new/grype-0.120.1/grype/presenter/table/presenter.go
--- old/grype-0.120.0/grype/presenter/table/presenter.go        2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/presenter/table/presenter.go        2026-10-06 
18:42:08.000000000 +0200
@@ -315,7 +315,6 @@
                        m,
                        getRecommendedVersions(m),
                ),
-               m.Vulnerability.Fix.Versions,
        )
 }
 
@@ -334,7 +333,7 @@
 
 const maxVersionFieldLength = 30
 
-func (p *Presenter) formatVersionsToDisplay(m models.Match, 
recommendedVersions *strset.Set) []string {
+func (p *Presenter) formatVersionsToDisplay(m models.Match, 
recommendedVersions *strset.Set) (versions []string, omittedAny bool) {
        hasMultipleVersions := len(m.Vulnerability.Fix.Versions) > 1
        shouldHighlightRecommended := hasMultipleVersions && 
recommendedVersions.Size() > 0
 
@@ -358,6 +357,7 @@
 
                        // skip not-necessarily-recommended versions if we're 
running out of space
                        if currentCharacterCount+len(v) > maxVersionFieldLength 
{
+                               omittedAny = true
                                continue
                        }
 
@@ -372,18 +372,14 @@
                }
        }
 
-       return vers
+       return vers, omittedAny
 }
 
-func (p *Presenter) applyTruncation(formattedVersions []string, allVersions 
[]string) string {
+func (p *Presenter) applyTruncation(formattedVersions []string, omittedAny 
bool) string {
        finalVersions := strings.Join(formattedVersions, 
p.auxiliaryStyle.Render(", "))
 
-       var characterCount int
-       for _, v := range allVersions {
-               characterCount += len(v)
-       }
-
-       if characterCount > maxVersionFieldLength && len(allVersions) > 1 {
+       // only hint at more versions when one was actually left out
+       if omittedAny {
                finalVersions += p.auxiliaryStyle.Render(", ...")
        }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/grype-0.120.0/grype/presenter/table/presenter_test.go 
new/grype-0.120.1/grype/presenter/table/presenter_test.go
--- old/grype-0.120.0/grype/presenter/table/presenter_test.go   2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/grype/presenter/table/presenter_test.go   2026-10-06 
18:42:08.000000000 +0200
@@ -112,6 +112,67 @@
        }
 }
 
+func TestFormatFix(t *testing.T) {
+       matchWithFixVersions := func(versions []string, recommended ...string) 
models.Match {
+               var details []models.MatchDetails
+               for _, r := range recommended {
+                       details = append(details, models.MatchDetails{
+                               Type:    match.ExactDirectMatch.String(),
+                               Matcher: match.DpkgMatcher.String(),
+                               Fix:     &models.FixDetails{SuggestedVersion: 
r},
+                       })
+               }
+               return models.Match{
+                       Vulnerability: models.Vulnerability{
+                               Fix: models.Fix{
+                                       Versions: versions,
+                                       State:    
vulnerability.FixStateFixed.String(),
+                               },
+                       },
+                       MatchDetails: details,
+               }
+       }
+
+       cases := []struct {
+               name     string
+               match    models.Match
+               expected string
+       }{
+               {
+                       name: "all recommended versions are shown without a 
truncation hint",
+                       match: matchWithFixVersions(
+                               []string{"10.20.30-alpha.1", 
"10.20.30-beta.11"},
+                               "10.20.30-alpha.1", "10.20.30-beta.11",
+                       ),
+                       expected: "*10.20.30-alpha.1, *10.20.30-beta.11",
+               },
+               {
+                       name: "a version dropped for space keeps the truncation 
hint",
+                       match: matchWithFixVersions(
+                               []string{"1.0.0", 
"2.0.0-really-long-version-string"},
+                               "1.0.0",
+                       ),
+                       expected: "*1.0.0, ...",
+               },
+               {
+                       name: "duplicate versions are not reported as 
truncated",
+                       match: matchWithFixVersions(
+                               []string{"10.20.30-alpha.1", 
"10.20.30-alpha.1"},
+                               "10.20.30-alpha.1",
+                       ),
+                       expected: "*10.20.30-alpha.1",
+               },
+       }
+
+       for _, testCase := range cases {
+               t.Run(testCase.name, func(t *testing.T) {
+                       p := NewPresenter(models.PresenterConfig{}, false)
+
+                       assert.Equal(t, testCase.expected, 
p.formatFix(testCase.match))
+               })
+       }
+}
+
 func TestTablePresenter(t *testing.T) {
        pb := internal.GeneratePresenterConfig(t, internal.ImageSource)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/internal/dbtest/builder.go 
new/grype-0.120.1/internal/dbtest/builder.go
--- old/grype-0.120.0/internal/dbtest/builder.go        2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/internal/dbtest/builder.go        2026-10-06 
18:42:08.000000000 +0200
@@ -339,10 +339,12 @@
 // "results/" segment is not present in the path, only the basename is returned
 // to fall back to the prior behavior.
 func relativeResultPath(path string) string {
-       const sep = string(filepath.Separator) + "results" + 
string(filepath.Separator)
+       // normalize to forward slashes so this behaves the same regardless of 
platform separators
+       const sep = "/results/"
+       path = filepath.ToSlash(path)
        idx := strings.LastIndex(path, sep)
        if idx < 0 {
-               return filepath.Base(path)
+               return filepath.Base(filepath.FromSlash(path))
        }
        return path[idx+len(sep):]
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/internal/dbtest/extractor_test.go 
new/grype-0.120.1/internal/dbtest/extractor_test.go
--- old/grype-0.120.0/internal/dbtest/extractor_test.go 2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/internal/dbtest/extractor_test.go 2026-10-06 
18:42:08.000000000 +0200
@@ -223,6 +223,12 @@
        connStr := "file:" + dbPath + "?cache=shared"
        db, err := gorm.Open(sqlite.Open(connStr), &gorm.Config{Logger: 
logger.Discard})
        require.NoError(t, err)
+       // windows can't remove the temp dir while the db is open
+       t.Cleanup(func() {
+               if d, err := db.DB(); err == nil {
+                       _ = d.Close()
+               }
+       })
 
        // create table
        require.NoError(t, db.AutoMigrate(&testResults{}))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/internal/format/writer_test.go 
new/grype-0.120.1/internal/format/writer_test.go
--- old/grype-0.120.0/internal/format/writer_test.go    2026-10-02 
15:23:52.000000000 +0200
+++ new/grype-0.120.1/internal/format/writer_test.go    2026-10-06 
18:42:08.000000000 +0200
@@ -1,6 +1,7 @@
 package format
 
 import (
+       "io"
        "path/filepath"
        "strings"
        "testing"
@@ -153,7 +154,7 @@
                        outputs := test.outputs
                        for i := range outputs {
                                if outputs[i].Path != "" {
-                                       outputs[i].Path = tmp + outputs[i].Path
+                                       outputs[i].Path = filepath.Join(tmp, 
outputs[i].Path)
                                }
                        }
 
@@ -165,6 +166,14 @@
                        } else {
                                assert.NoError(t, err)
                        }
+                       // release file handles so the temp dir can be removed 
(required on windows)
+                       t.Cleanup(func() {
+                               for _, w := range mw.writers {
+                                       if c, ok := w.(io.Closer); ok {
+                                               _ = c.Close()
+                                       }
+                               }
+                       })
 
                        assert.Len(t, mw.writers, len(test.expected))
 
@@ -174,7 +183,7 @@
                                        assert.Equal(t, string(w.format), 
e.format)
                                        assert.NotNil(t, w.out)
                                        if e.file != "" {
-                                               assert.FileExists(t, tmp+e.file)
+                                               assert.FileExists(t, 
filepath.Join(tmp, e.file))
                                        }
                                case *scanResultPublisher:
                                        assert.Equal(t, string(w.format), 
e.format)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.120.0/test/containers-storage/source-test.sh 
new/grype-0.120.1/test/containers-storage/source-test.sh
--- old/grype-0.120.0/test/containers-storage/source-test.sh    1970-01-01 
01:00:00.000000000 +0100
+++ new/grype-0.120.1/test/containers-storage/source-test.sh    2026-10-06 
18:42:08.000000000 +0200
@@ -0,0 +1,144 @@
+#!/usr/bin/env bash
+# build an image with podman or buildah into an isolated containers-storage 
store, then verify grype can scan it out
+# of that store (for both the vfs and overlay drivers) and that plain image 
references never touch the store.
+#
+# usage: GRYPE_BINARY_LOCATION=/path/to/grype source-test.sh podman|buildah
+set -euo pipefail
+
+builder="${1:?expected podman or buildah}"
+case "$builder" in
+  podman|buildah) ;;
+  *)
+    printf 'unsupported image builder: %s\n' "$builder" >&2
+    exit 2
+    ;;
+esac
+
+grype_binary="${GRYPE_BINARY_LOCATION:?expected GRYPE_BINARY_LOCATION to point 
at a linux grype binary built with containers-storage support}"
+if [[ ! -f "$grype_binary" ]]; then
+  printf 'grype binary not found at %s\n' "$grype_binary" >&2
+  exit 1
+fi
+chmod +x "$grype_binary"
+
+test_dir="$(mktemp -d)"
+# the overlay driver bind-mounts its graphroot onto itself (in the builder's 
user namespace when rootless), which must
+# be unmounted before the store can be removed. Cleanup is best-effort so it 
never masks the test result.
+cleanup_store() {
+  umount -l "$1"/*/graphroot/overlay 2>/dev/null || true
+  rm -rf "$1"
+}
+cleanup() {
+  if [[ "$(id -u)" -eq 0 ]]; then
+    cleanup_store "$test_dir"
+  else
+    "$builder" unshare bash -c "$(declare -f cleanup_store); cleanup_store 
\"\$1\"" _ "$test_dir"
+  fi || printf 'warning: unable to fully clean up %s\n' "$test_dir" >&2
+}
+trap cleanup EXIT
+
+# a rootless store can only be opened from inside the builder's user namespace 
(as podman/buildah/skopeo do for
+# themselves), so rootless users must run grype under "<builder> unshare". 
Root opens the store directly.
+run_grype() {
+  if [[ "$(id -u)" -eq 0 ]]; then
+    "$grype_binary" "$@"
+  else
+    "$builder" unshare "$grype_binary" "$@"
+  fi
+}
+
+export GRYPE_CHECK_FOR_APP_UPDATE=false
+export GRYPE_DB_CACHE_DIR="$test_dir/db"
+"$grype_binary" db update
+export GRYPE_DB_AUTO_UPDATE=false
+
+# lodash 4.17.20 has known vulnerabilities, so a match proves the package was 
cataloged out of the image
+build_context="$test_dir/context"
+mkdir -p "$build_context"
+cat > "$build_context/package.json" <<'EOF'
+{"name":"lodash","version":"4.17.20"}
+EOF
+cat > "$build_context/Containerfile" <<'EOF'
+FROM scratch
+COPY package.json /app/node_modules/lodash/package.json
+EOF
+
+# note: the image name deliberately avoids the string "containers-storage" so 
stderr greps below are unambiguous
+image_ref="localhost/grype-cs-fixture:latest"
+missing_ref="localhost/grype-cs-missing:latest"
+
+for driver in vfs overlay; do
+  store_dir="$test_dir/$driver"
+  mkdir -p "$store_dir"
+  export CONTAINERS_STORAGE_CONF="$store_dir/storage.conf"
+  cat > "$CONTAINERS_STORAGE_CONF" <<EOF
+[storage]
+driver = "$driver"
+graphroot = "$store_dir/graphroot"
+rootless_storage_path = "$store_dir/graphroot"
+runroot = "$store_dir/runroot"
+EOF
+
+  printf 'Building %s with %s (%s driver)\n' "$image_ref" "$builder" "$driver"
+  case "$builder" in
+    podman)
+      podman build --pull=never --tag "$image_ref" "$build_context"
+      ;;
+    buildah)
+      buildah build --pull=false --tag "$image_ref" "$build_context"
+      ;;
+  esac
+
+  for scan_mode in from-flag scheme default-pull-source; do
+    printf 'Testing %s resolution with %s (%s driver)\n' "$scan_mode" 
"$builder" "$driver"
+    out="$store_dir/$scan_mode"
+    case "$scan_mode" in
+      from-flag)
+        run_grype -vv --from containers-storage "$image_ref" --output json > 
"$out.json" 2> "$out.stderr"
+        ;;
+      scheme)
+        run_grype -vv "containers-storage:$image_ref" --output json > 
"$out.json" 2> "$out.stderr"
+        ;;
+      default-pull-source)
+        GRYPE_DEFAULT_IMAGE_PULL_SOURCE=containers-storage \
+          run_grype -vv "$image_ref" --output json > "$out.json" 2> 
"$out.stderr"
+        ;;
+    esac
+
+    # prove the image came out of the store, not from some other provider that 
happened to answer
+    if ! grep -q 'copied image from containers-storage' "$out.stderr"; then
+      printf 'Expected %s scan to resolve via containers-storage\n' 
"$scan_mode" >&2
+      cat "$out.stderr" >&2
+      exit 1
+    fi
+    jq -e --arg image_ref "$image_ref" '
+      .source.type == "image" and
+      .source.target.userInput == $image_ref and
+      any(.matches[].artifact; .name == "lodash" and .version == "4.17.20" and 
.type == "npm")
+    ' "$out.json" >/dev/null
+  done
+
+  printf 'Testing plain reference skips containers-storage with %s (%s 
driver)\n' "$builder" "$driver"
+  # the image only exists in the local store, so automatic resolution 
(daemons, then registry) must fail without
+  # ever trying containers-storage
+  if run_grype "$image_ref" --output json > "$store_dir/plain.json" 2> 
"$store_dir/plain.stderr"; then
+    printf 'Expected plain reference scan to fail since the image only exists 
in containers-storage\n' >&2
+    exit 1
+  fi
+  if grep -q 'containers-storage' "$store_dir/plain.stderr"; then
+    printf 'Plain reference unexpectedly attempted containers-storage 
resolution\n' >&2
+    cat "$store_dir/plain.stderr" >&2
+    exit 1
+  fi
+
+  printf 'Testing missing image with %s (%s driver)\n' "$builder" "$driver"
+  if run_grype --from containers-storage "$missing_ref" --output json > 
"$store_dir/missing.json" 2> "$store_dir/missing.stderr"; then
+    printf 'Expected the missing containers-storage image scan to fail\n' >&2
+    exit 1
+  fi
+  if ! grep -q 'does not resolve to an image ID' "$store_dir/missing.stderr"; 
then
+    printf 'Expected a containers-storage "image not found" error\n' >&2
+    cat "$store_dir/missing.stderr" >&2
+    exit 1
+  fi
+done

++++++ grype.obsinfo ++++++
--- /var/tmp/diff_new_pack.MDryGX/_old  2026-10-07 19:34:06.072389065 +0200
+++ /var/tmp/diff_new_pack.MDryGX/_new  2026-10-07 19:34:06.076389233 +0200
@@ -1,5 +1,5 @@
 name: grype
-version: 0.120.0
-mtime: 1790947432
-commit: 10fbc043ecbaf8436daa9efac9f1632557caf277
+version: 0.120.1
+mtime: 1791304928
+commit: 6f8d854af29d3a3086b11a84afa51554a2a245fe
 

++++++ vendor.tar.gz ++++++
/work/SRC/openSUSE:Factory/grype/vendor.tar.gz 
/work/SRC/openSUSE:Factory/.grype.new.3698736/vendor.tar.gz differ: char 134, 
line 2

Reply via email to