Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package grype for openSUSE:Factory checked 
in at 2025-05-22 16:55:53
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/grype (Old)
 and      /work/SRC/openSUSE:Factory/.grype.new.2732 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "grype"

Thu May 22 16:55:53 2025 rev:91 rq:1278913 version:0.92.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/grype/grype.changes      2025-05-20 
10:36:45.049493639 +0200
+++ /work/SRC/openSUSE:Factory/.grype.new.2732/grype.changes    2025-05-22 
16:55:56.923574522 +0200
@@ -1,0 +2,17 @@
+Wed May 21 04:29:32 UTC 2025 - Johannes Kastl 
<opensuse_buildserv...@ojkastl.de>
+
+- Update to version 0.92.2:
+  * Bug Fixes
+    - unpin dockerfile base images to prevent wget TLS errors
+      [#2671 @spiffcs]
+    - Parse java group ID and artifact ID from PURL when missing
+      [#2675 @wagoodman]
+    - Grype can't update DB in docker volume (regression) [#2517
+      #2672 @willmurphyscode]
+  * Additional Changes
+    - Remove getDB() from the v6 DB reader [#2669 @wagoodman]
+  * Dependencies
+    - chore(deps): update anchore dependencies (#2676)
+    - chore(deps): update tools to latest versions (#2673)
+
+-------------------------------------------------------------------

Old:
----
  grype-0.92.1.obscpio

New:
----
  grype-0.92.2.obscpio

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

Other differences:
------------------
++++++ grype.spec ++++++
--- /var/tmp/diff_new_pack.gPyM6X/_old  2025-05-22 16:55:59.291674908 +0200
+++ /var/tmp/diff_new_pack.gPyM6X/_new  2025-05-22 16:55:59.295675079 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           grype
-Version:        0.92.1
+Version:        0.92.2
 Release:        0
 Summary:        A vulnerability scanner for container images and filesystems
 License:        Apache-2.0

++++++ _service ++++++
--- /var/tmp/diff_new_pack.gPyM6X/_old  2025-05-22 16:55:59.331676604 +0200
+++ /var/tmp/diff_new_pack.gPyM6X/_new  2025-05-22 16:55:59.331676604 +0200
@@ -3,7 +3,7 @@
     <param name="url">https://github.com/anchore/grype</param>
     <param name="scm">git</param>
     <param name="exclude">.git</param>
-    <param name="revision">v0.92.1</param>
+    <param name="revision">v0.92.2</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.gPyM6X/_old  2025-05-22 16:55:59.351677452 +0200
+++ /var/tmp/diff_new_pack.gPyM6X/_new  2025-05-22 16:55:59.355677622 +0200
@@ -1,6 +1,6 @@
 <servicedata>
 <service name="tar_scm">
                 <param name="url">https://github.com/anchore/grype</param>
-              <param 
name="changesrevision">4d630fdfd3e8b2d4e3c02674c60bf355dfba4d7b</param></service></servicedata>
+              <param 
name="changesrevision">3f52c46d440ac17b2924c633826ce8fd30a5e16d</param></service></servicedata>
 (No newline at EOF)
 

++++++ grype-0.92.1.obscpio -> grype-0.92.2.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.92.1/.binny.yaml new/grype-0.92.2/.binny.yaml
--- old/grype-0.92.1/.binny.yaml        2025-05-16 21:48:10.000000000 +0200
+++ new/grype-0.92.2/.binny.yaml        2025-05-21 00:12:30.000000000 +0200
@@ -98,7 +98,7 @@
   # used for triggering a release
   - name: gh
     version:
-      want: v2.72.0
+      want: v2.73.0
     method: github-release
     with:
       repo: cli/cli
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.92.1/Dockerfile new/grype-0.92.2/Dockerfile
--- old/grype-0.92.1/Dockerfile 2025-05-16 21:48:10.000000000 +0200
+++ new/grype-0.92.2/Dockerfile 2025-05-21 00:12:30.000000000 +0200
@@ -1,5 +1,4 @@
-FROM 
gcr.io/distroless/static-debian11@sha256:5759d194607e472ff80fff5833442d3991dd89b219c96552837a2c8f74058617
 AS build
-
+FROM gcr.io/distroless/static-debian12:latest AS build
 
 FROM scratch
 # needed for version check HTTPS request
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.92.1/Dockerfile.debug 
new/grype-0.92.2/Dockerfile.debug
--- old/grype-0.92.1/Dockerfile.debug   2025-05-16 21:48:10.000000000 +0200
+++ new/grype-0.92.2/Dockerfile.debug   2025-05-21 00:12:30.000000000 +0200
@@ -1,5 +1,4 @@
-FROM 
gcr.io/distroless/static-debian11:debug@sha256:c66a6ecb5aa7704a68c89d3ead1398adc7f16e214dda5f5f8e5d44351bcbf67d
-
+FROM gcr.io/distroless/static-debian12:debug
 
 # create the /tmp dir, which is needed for image content cache
 WORKDIR /tmp
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.92.1/go.mod new/grype-0.92.2/go.mod
--- old/grype-0.92.1/go.mod     2025-05-16 21:48:10.000000000 +0200
+++ new/grype-0.92.2/go.mod     2025-05-21 00:12:30.000000000 +0200
@@ -19,7 +19,7 @@
        github.com/anchore/go-version v1.2.2-0.20210903204242-51efa5b487c4
        github.com/anchore/packageurl-go v0.1.1-0.20250220190351-d62adb6e1115
        github.com/anchore/stereoscope v0.1.4
-       github.com/anchore/syft v1.25.1
+       github.com/anchore/syft v1.26.0
        github.com/aquasecurity/go-pep440-version v0.0.1
        github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de
        github.com/bmatcuk/doublestar/v2 v2.0.4
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.92.1/go.sum new/grype-0.92.2/go.sum
--- old/grype-0.92.1/go.sum     2025-05-16 21:48:10.000000000 +0200
+++ new/grype-0.92.2/go.sum     2025-05-21 00:12:30.000000000 +0200
@@ -710,8 +710,8 @@
 github.com/anchore/packageurl-go v0.1.1-0.20250220190351-d62adb6e1115/go.mod 
h1:KoYIv7tdP5+CC9VGkeZV4/vGCKsY55VvoG+5dadg4YI=
 github.com/anchore/stereoscope v0.1.4 
h1:e+iT9UdUzLBabWGe84hn5sTHDRioY+4IHsVzJXuJlek=
 github.com/anchore/stereoscope v0.1.4/go.mod 
h1:omWgXDEp/XfqCJlZXIByEo1c3ArZg/qTJ5LBKVLAIdw=
-github.com/anchore/syft v1.25.1 h1:HaG5/0r1UdZ7zyscEFeFz0pQsBLTXdCgEDXa5LqFjcg=
-github.com/anchore/syft v1.25.1/go.mod 
h1:xa15pYmHrXKe7IlvaO+EAD/krawWYUtILTpMcL/S+Gw=
+github.com/anchore/syft v1.26.0 h1:u3x143wnU9ZuKxksrTugUtZ2dt1hY9fpc8dbd/iMysI=
+github.com/anchore/syft v1.26.0/go.mod 
h1:xa15pYmHrXKe7IlvaO+EAD/krawWYUtILTpMcL/S+Gw=
 github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod 
h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
 github.com/andybalholm/brotli v1.0.4/go.mod 
h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
 github.com/andybalholm/brotli v1.1.2-0.20250424173009-453214e765f3 
h1:8PmGpDEZl9yDpcdEr6Odf23feCxK3LNUNMxjXg41pZQ=
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.92.1/grype/db/v6/db.go 
new/grype-0.92.2/grype/db/v6/db.go
--- old/grype-0.92.1/grype/db/v6/db.go  2025-05-16 21:48:10.000000000 +0200
+++ new/grype-0.92.2/grype/db/v6/db.go  2025-05-21 00:12:30.000000000 +0200
@@ -57,7 +57,6 @@
        AffectedPackageStoreReader
        AffectedCPEStoreReader
        io.Closer
-       getDB() *gorm.DB
        attachBlobValue(...blobable) error
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.92.1/grype/db/v6/installation/curator.go 
new/grype-0.92.2/grype/db/v6/installation/curator.go
--- old/grype-0.92.1/grype/db/v6/installation/curator.go        2025-05-16 
21:48:10.000000000 +0200
+++ new/grype-0.92.2/grype/db/v6/installation/curator.go        2025-05-21 
00:12:30.000000000 +0200
@@ -298,7 +298,14 @@
        if err != nil {
                return nil, fmt.Errorf("unable to resolve vulnerability DB URL: 
%w", err)
        }
-       dest, err := c.client.Download(url, filepath.Dir(c.config.DBRootDir), 
mon.downloadProgress.Manual)
+
+       // Ensure parent of DBRootDir exists for the download client to create 
a temp dir within DBRootDir
+       // This might be redundant if DBRootDir must already exist, but good 
for safety.
+       if err := os.MkdirAll(c.config.DBRootDir, 0o700); err != nil {
+               return nil, fmt.Errorf("unable to create db root dir %s for 
download: %w", c.config.DBRootDir, err)
+       }
+
+       dest, err := c.client.Download(url, c.config.DBRootDir, 
mon.downloadProgress.Manual)
        if err != nil {
                return nil, fmt.Errorf("unable to update vulnerability 
database: %w", err)
        }
@@ -307,6 +314,8 @@
 
        mon.downloadProgress.SetCompleted()
        if err = c.activate(dest, url, mon); err != nil {
+               log.Warnf("Failed to activate downloaded database from %s, 
attempting cleanup of temporary download directory.", dest)
+               removeAllOrLog(c.fs, dest)
                return nil, fmt.Errorf("unable to activate new vulnerability 
database: %w", err)
        }
 
@@ -397,7 +406,7 @@
        // is a prerequisite for a successful update).
 
        filePath := filepath.Join(c.config.DBDirectoryPath(), 
lastUpdateCheckFileName)
-       fh, err := c.fs.OpenFile(filePath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 
0644)
+       fh, err := c.fs.OpenFile(filePath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 
0o644)
        if err != nil {
                log.WithFields("error", err).Trace("unable to write last update 
check timestamp")
                return
@@ -414,7 +423,7 @@
        mon.Set("preparing")
        defer mon.SetCompleted()
 
-       if err := os.MkdirAll(c.config.DBRootDir, 0700); err != nil {
+       if err := os.MkdirAll(c.config.DBRootDir, 0o700); err != nil {
                return fmt.Errorf("unable to create db root dir: %w", err)
        }
 
@@ -424,7 +433,7 @@
                mon.Set("downloading")
                var err error
 
-               tempDir, err = c.client.Download(reference, 
filepath.Dir(c.config.DBRootDir), mon.downloadProgress.Manual)
+               tempDir, err = c.client.Download(reference, c.config.DBRootDir, 
mon.downloadProgress.Manual)
                if err != nil {
                        return fmt.Errorf("unable to update vulnerability 
database: %w", err)
                }
@@ -526,12 +535,17 @@
        }
 
        // ensure parent db directory exists
-       if err := c.fs.MkdirAll(filepath.Dir(dbDir), 0700); err != nil {
+       if err = c.fs.MkdirAll(filepath.Dir(dbDir), 0o700); err != nil {
                return fmt.Errorf("unable to create db parent directory: %w", 
err)
        }
 
        // activate the new db cache by moving the temp dir to final location
+       // the rename should be safe because the temp dir is under 
GRYPE_DB_CACHE_DIR
+       // and so on the same filesystem as the final location
        err = c.fs.Rename(dbDirPath, dbDir)
+       if err != nil {
+               err = fmt.Errorf("failed to move database directory to 
activate: %w", err)
+       }
        log.WithFields("from", dbDirPath, "to", dbDir, "error", 
err).Debug("moved database directory to activate")
        return err
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/grype-0.92.1/grype/db/v6/installation/curator_test.go 
new/grype-0.92.2/grype/db/v6/installation/curator_test.go
--- old/grype-0.92.1/grype/db/v6/installation/curator_test.go   2025-05-16 
21:48:10.000000000 +0200
+++ new/grype-0.92.2/grype/db/v6/installation/curator_test.go   2025-05-21 
00:12:30.000000000 +0200
@@ -758,6 +758,153 @@
        }
 }
 
+func TestCurator_Update_UsesDBRootDirForDownloadTempBase(t *testing.T) {
+       c := newTestCurator(t) // This sets up c.fs as afero.NewOsFs() rooted 
in t.TempDir()
+       mc := c.client.(*mockClient)
+
+       // This is the path that the mocked Download method will return.
+       // It simulates a temporary directory created by the download client 
within DBRootDir.
+       expectedDownloadedContentPath := filepath.Join(c.config.DBRootDir, 
"temp-downloaded-db-content-123")
+
+       // Pre-create this directory and make it look like a valid DB source 
for the hydrator and replaceDB.
+       require.NoError(t, c.fs.MkdirAll(expectedDownloadedContentPath, 0755))
+       // Write minimal valid DB metadata so that hydration/activation can 
proceed far enough.
+       // Using existing helpers to create a semblance of a DB.
+       writeTestDB(t, c.fs, expectedDownloadedContentPath) // This creates a 
basic DB file and import metadata.
+
+       // Mock client responses
+       mc.On("IsUpdateAvailable", 
mock.Anything).Return(&distribution.Archive{}, nil)
+       // CRUCIAL ASSERTION:
+       // Verify that Download is called with c.config.DBRootDir as its second 
argument (baseDirForTemp).
+       // It will return the expectedDownloadedContentPath, simulating 
successful download and extraction.
+       mc.On("Download", mock.Anything, c.config.DBRootDir, 
mock.Anything).Return(expectedDownloadedContentPath, nil)
+
+       hydrateCalled := false
+       c.hydrator = func(path string) error {
+               // Ensure hydrator is called with the path returned by Download
+               assert.Equal(t, expectedDownloadedContentPath, path, "hydrator 
called with incorrect path")
+               hydrateCalled = true
+               return nil // Simulate successful hydration
+       }
+
+       // Call Update to trigger the download and activation sequence
+       updated, err := c.Update()
+
+       // Assertions
+       require.NoError(t, err, "Update should succeed")
+       require.True(t, updated, "Update should report true")
+       mc.AssertExpectations(t) // Verifies that Download was called with the 
expected arguments
+       assert.True(t, hydrateCalled, "expected hydrator to be called")
+
+       // Check if the DB was "activated" (i.e., renamed)
+       finalDBPath := c.config.DBDirectoryPath()
+       _, err = c.fs.Stat(finalDBPath)
+       require.NoError(t, err, "final DB directory should exist after 
successful update")
+       // And the temporary downloaded content path should no longer exist as 
it was renamed
+       _, err = c.fs.Stat(expectedDownloadedContentPath)
+       require.True(t, os.IsNotExist(err), "temporary download path should not 
exist after rename")
+}
+
+func TestCurator_Update_CleansUpDownloadDirOnActivationFailure(t *testing.T) {
+       c := newTestCurator(t) // Sets up c.fs as afero.NewOsFs() rooted in 
t.TempDir()
+       mc := c.client.(*mockClient)
+
+       // This is the path that the mocked Download method will return.
+       // This directory should be cleaned up if activation fails.
+       downloadedContentPath := filepath.Join(c.config.DBRootDir, 
"temp-download-to-be-cleaned-up")
+
+       // Simulate the download client successfully creating this directory.
+       require.NoError(t, c.fs.MkdirAll(downloadedContentPath, 0755))
+       // Optionally, put a dummy file inside to make the cleanup more 
tangible.
+       require.NoError(t, afero.WriteFile(c.fs, 
filepath.Join(downloadedContentPath, "dummy_file.txt"), []byte("test data"), 
0644))
+
+       // Mock client responses
+       mc.On("IsUpdateAvailable", 
mock.Anything).Return(&distribution.Archive{}, nil)
+       // Download is called with DBRootDir as base, and returns the path to 
the (simulated) downloaded content.
+       mc.On("Download", mock.Anything, c.config.DBRootDir, 
mock.Anything).Return(downloadedContentPath, nil)
+
+       // Configure the hydrator to fail, which will cause c.activate() to 
fail.
+       expectedHydrationError := "simulated hydration failure"
+       c.hydrator = func(path string) error {
+               assert.Equal(t, downloadedContentPath, path, "hydrator called 
with incorrect path")
+               return errors.New(expectedHydrationError)
+       }
+
+       // Call Update, expecting it to fail during activation.
+       updated, err := c.Update()
+
+       // Assertions
+       require.Error(t, err, "Update should fail due to activation error")
+       require.Contains(t, err.Error(), expectedHydrationError, "Error message 
should reflect hydration failure")
+       require.False(t, updated, "Update should report false on failure")
+       mc.AssertExpectations(t) // Verifies Download was called as expected.
+
+       // CRUCIAL ASSERTION:
+       // Verify that the temporary download directory was cleaned up.
+       _, statErr := c.fs.Stat(downloadedContentPath)
+       require.True(t, os.IsNotExist(statErr), "expected temporary download 
directory to be cleaned up after activation failure")
+}
+
+// Test for the Import path (URL case) - very similar to the Update tests
+func TestCurator_Import_URL_UsesDBRootDirForDownloadTempBaseAndCleansUp(t 
*testing.T) {
+       t.Run("successful import from URL", func(t *testing.T) {
+               c := newTestCurator(t)
+               mc := c.client.(*mockClient)
+
+               importURL := "http://localhost/some/db.tar.gz";
+               expectedDownloadedContentPath := 
filepath.Join(c.config.DBRootDir, "temp-imported-db-content-url")
+
+               require.NoError(t, c.fs.MkdirAll(expectedDownloadedContentPath, 
0755))
+               writeTestDB(t, c.fs, expectedDownloadedContentPath)
+
+               mc.On("Download", importURL, c.config.DBRootDir, 
mock.Anything).Return(expectedDownloadedContentPath, nil)
+
+               hydrateCalled := false
+               c.hydrator = func(path string) error {
+                       assert.Equal(t, expectedDownloadedContentPath, path)
+                       hydrateCalled = true
+                       return nil
+               }
+
+               err := c.Import(importURL)
+
+               require.NoError(t, err)
+               mc.AssertExpectations(t)
+               assert.True(t, hydrateCalled)
+               _, err = c.fs.Stat(c.config.DBDirectoryPath())
+               require.NoError(t, err, "final DB directory should exist")
+               _, err = c.fs.Stat(expectedDownloadedContentPath)
+               require.True(t, os.IsNotExist(err), "temp import path should 
not exist after rename")
+       })
+
+       t.Run("import from URL fails activation", func(t *testing.T) {
+               c := newTestCurator(t)
+               mc := c.client.(*mockClient)
+
+               importURL := "http://localhost/some/other/db.tar.gz";
+               downloadedContentPath := filepath.Join(c.config.DBRootDir, 
"temp-imported-to-cleanup-url")
+
+               require.NoError(t, c.fs.MkdirAll(downloadedContentPath, 0755))
+               require.NoError(t, afero.WriteFile(c.fs, 
filepath.Join(downloadedContentPath, "dummy.txt"), []byte("test"), 0644))
+
+               mc.On("Download", importURL, c.config.DBRootDir, 
mock.Anything).Return(downloadedContentPath, nil)
+
+               expectedHydrationError := "simulated hydration failure for 
import"
+               c.hydrator = func(path string) error {
+                       return errors.New(expectedHydrationError)
+               }
+
+               err := c.Import(importURL)
+
+               require.Error(t, err)
+               require.Contains(t, err.Error(), expectedHydrationError)
+               mc.AssertExpectations(t)
+
+               _, statErr := c.fs.Stat(downloadedContentPath)
+               require.True(t, os.IsNotExist(statErr), "expected temp import 
directory to be cleaned up")
+       })
+}
+
 func setupTestDB(t *testing.T, dbDir string) db.ReadWriter {
        s, err := db.NewWriter(db.Config{
                DBDirPath: dbDir,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.92.1/grype/db/v6/refs.go 
new/grype-0.92.2/grype/db/v6/refs.go
--- old/grype-0.92.1/grype/db/v6/refs.go        2025-05-16 21:48:10.000000000 
+0200
+++ new/grype-0.92.2/grype/db/v6/refs.go        2025-05-21 00:12:30.000000000 
+0200
@@ -2,6 +2,8 @@
 
 import (
        "slices"
+
+       "gorm.io/gorm"
 )
 
 type ref[ID, T any] struct {
@@ -38,7 +40,7 @@
 
        // load a map with all id -> ref results
        var values []R
-       tx := reader.getDB().Where("id IN (?)", ids)
+       tx := reader.(lowLevelReader).GetDB().Where("id IN (?)", ids)
        err := tx.Find(&values).Error
        if err != nil {
                return err
@@ -73,3 +75,7 @@
        }
        return out
 }
+
+type lowLevelReader interface {
+       GetDB() *gorm.DB
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.92.1/grype/db/v6/store.go 
new/grype-0.92.2/grype/db/v6/store.go
--- old/grype-0.92.1/grype/db/v6/store.go       2025-05-16 21:48:10.000000000 
+0200
+++ new/grype-0.92.2/grype/db/v6/store.go       2025-05-21 00:12:30.000000000 
+0200
@@ -23,7 +23,7 @@
        writable  bool
 }
 
-func (s *store) getDB() *gorm.DB {
+func (s *store) GetDB() *gorm.DB {
        return s.db
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.92.1/grype/pkg/package.go 
new/grype-0.92.2/grype/pkg/package.go
--- old/grype-0.92.1/grype/pkg/package.go       2025-05-16 21:48:10.000000000 
+0200
+++ new/grype-0.92.2/grype/pkg/package.go       2025-05-21 00:12:30.000000000 
+0200
@@ -212,6 +212,7 @@
        var metadata interface{}
        var upstreams []UpstreamPackage
 
+       // use the metadata to determine the type of package
        switch p.Metadata.(type) {
        case syftPkg.GolangModuleEntry, syftPkg.GolangBinaryBuildinfoEntry:
                metadata = golangMetadataFromPkg(p)
@@ -226,7 +227,7 @@
                        metadata = *m
                }
        case syftPkg.JavaArchive:
-               if m := javaDataFromPkg(p); m != nil {
+               if m := javaDataFromPkgMetadata(p); m != nil {
                        metadata = *m
                }
        case syftPkg.ApkDBEntry:
@@ -236,6 +237,13 @@
                metadata = javaVMDataFromPkg(p)
        }
 
+       // there are still cases where we could still fill the metadata from 
other info (such as the PURL)
+       if metadata == nil {
+               if p.Type == syftPkg.JavaPkg {
+                       metadata = javaDataFromPkgData(p)
+               }
+       }
+
        return metadata, upstreams
 }
 
@@ -309,7 +317,7 @@
                        })
                }
        default:
-               log.Warnf("unable to extract DPKG metadata for %s", p)
+               log.Debugf("unable to extract DPKG metadata for %s", p)
        }
 
        return upstreams
@@ -343,7 +351,7 @@
        var upstreams []UpstreamPackage
        name, version := getNameAndELVersion(sourceRpm)
        if name == "" && version == "" {
-               log.Warnf("unable to extract name and version from SourceRPM=%q 
", sourceRpm)
+               log.Debugf("unable to extract name and version from 
SourceRPM=%q", sourceRpm)
        } else if name != pkgName {
                // don't include matches if the source package name matches the 
current package name
                if name != "" && version != "" {
@@ -364,13 +372,17 @@
        return groupMatches["name"], version
 }
 
-func javaDataFromPkg(p syftPkg.Package) (metadata *JavaMetadata) {
+func javaDataFromPkgMetadata(p syftPkg.Package) (metadata *JavaMetadata) {
        if value, ok := p.Metadata.(syftPkg.JavaArchive); ok {
                var artifactID, groupID, name string
                if value.PomProperties != nil {
                        artifactID = value.PomProperties.ArtifactID
                        groupID = value.PomProperties.GroupID
+               } else {
+                       // get the group ID / artifact ID from the PURL
+                       artifactID, groupID = 
javaGroupArtifactIDFromPurl(p.PURL)
                }
+
                if value.Manifest != nil {
                        for _, kv := range value.Manifest.Main {
                                if kv.Key == "Name" {
@@ -396,12 +408,36 @@
                        ManifestName:   name,
                        ArchiveDigests: archiveDigests,
                }
-       } else {
-               log.Warnf("unable to extract Java metadata for %s", p)
        }
        return metadata
 }
 
+func javaDataFromPkgData(p syftPkg.Package) (metadata *JavaMetadata) {
+       switch p.Type {
+       case syftPkg.JavaPkg:
+               artifactID, groupID := javaGroupArtifactIDFromPurl(p.PURL)
+               if artifactID != "" && groupID != "" {
+                       metadata = &JavaMetadata{
+                               PomArtifactID: artifactID,
+                               PomGroupID:    groupID,
+                       }
+               }
+       default:
+               log.Debugf("unable to extract metadata for %s", p)
+       }
+
+       return metadata
+}
+
+func javaGroupArtifactIDFromPurl(p string) (string, string) {
+       purl, err := packageurl.FromString(p)
+       if err != nil {
+               log.WithFields("purl", purl, "error", err).Debug("unable to 
parse java PURL")
+               return "", ""
+       }
+       return purl.Name, purl.Namespace
+}
+
 func apkDataFromPkg(p syftPkg.Package) (upstreams []UpstreamPackage) {
        if value, ok := p.Metadata.(syftPkg.ApkDBEntry); ok {
                if value.OriginPackage != "" {
@@ -410,7 +446,7 @@
                        })
                }
        } else {
-               log.Warnf("unable to extract APK metadata for %s", p)
+               log.Debugf("unable to extract APK metadata for %s", p)
        }
        return upstreams
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.92.1/grype/pkg/package_test.go 
new/grype-0.92.2/grype/pkg/package_test.go
--- old/grype-0.92.1/grype/pkg/package_test.go  2025-05-16 21:48:10.000000000 
+0200
+++ new/grype-0.92.2/grype/pkg/package_test.go  2025-05-21 00:12:30.000000000 
+0200
@@ -842,6 +842,19 @@
                                },
                        },
                },
+               {
+                       name: "pe binary metadata",
+                       syftPkg: syftPkg.Package{
+                               Metadata: syftPkg.PEBinary{
+                                       VersionResources: syftPkg.KeyValues{
+                                               {
+                                                       Key:   "k",
+                                                       Value: "k",
+                                               },
+                                       },
+                               },
+                       },
+               },
        }
 
        // capture each observed metadata type, we should see all of them 
relate to what syft provides by the end of testing
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/grype-0.92.1/grype/pkg/purl_provider_test.go 
new/grype-0.92.2/grype/pkg/purl_provider_test.go
--- old/grype-0.92.1/grype/pkg/purl_provider_test.go    2025-05-16 
21:48:10.000000000 +0200
+++ new/grype-0.92.2/grype/pkg/purl_provider_test.go    2025-05-21 
00:12:30.000000000 +0200
@@ -40,6 +40,29 @@
                        },
                },
                {
+                       name:      "java metadata decoded from purl",
+                       userInput: 
"pkg:maven/org.apache.commons/commons-lang3@3.12.0",
+                       context: Context{
+                               Source: &source.Description{
+                                       Metadata: PURLLiteralMetadata{
+                                               PURL: 
"pkg:maven/org.apache.commons/commons-lang3@3.12.0",
+                                       },
+                               },
+                       },
+                       pkgs: []Package{
+                               {
+                                       Name:    "commons-lang3",
+                                       Version: "3.12.0",
+                                       Type:    pkg.JavaPkg,
+                                       PURL:    
"pkg:maven/org.apache.commons/commons-lang3@3.12.0",
+                                       Metadata: JavaMetadata{
+                                               PomArtifactID: "commons-lang3",
+                                               PomGroupID:    
"org.apache.commons",
+                                       },
+                               },
+                       },
+               },
+               {
                        name:      "os with codename",
                        userInput: 
"pkg:deb/debian/sysv-rc@2.88dsf-59?arch=all&distro=debian-jessie&upstream=sysvinit",
                        context: Context{

++++++ grype.obsinfo ++++++
--- /var/tmp/diff_new_pack.gPyM6X/_old  2025-05-22 16:56:03.207840918 +0200
+++ /var/tmp/diff_new_pack.gPyM6X/_new  2025-05-22 16:56:03.211841087 +0200
@@ -1,5 +1,5 @@
 name: grype
-version: 0.92.1
-mtime: 1747424890
-commit: 4d630fdfd3e8b2d4e3c02674c60bf355dfba4d7b
+version: 0.92.2
+mtime: 1747779150
+commit: 3f52c46d440ac17b2924c633826ce8fd30a5e16d
 

++++++ vendor.tar.gz ++++++
/work/SRC/openSUSE:Factory/grype/vendor.tar.gz 
/work/SRC/openSUSE:Factory/.grype.new.2732/vendor.tar.gz differ: char 14, line 1

Reply via email to