Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package grype-db for openSUSE:Factory checked in at 2026-01-28 15:13:52 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/grype-db (Old) and /work/SRC/openSUSE:Factory/.grype-db.new.1928 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "grype-db" Wed Jan 28 15:13:52 2026 rev:27 rq:1329609 version:0.49.0 Changes: -------- --- /work/SRC/openSUSE:Factory/grype-db/grype-db.changes 2026-01-21 14:18:17.325230559 +0100 +++ /work/SRC/openSUSE:Factory/.grype-db.new.1928/grype-db.changes 2026-01-28 15:17:07.770927082 +0100 @@ -1,0 +2,29 @@ +Wed Jan 28 06:19:08 UTC 2026 - Johannes Kastl <[email protected]> + +- Update to version 0.49.0: + * Added Features + - turn on EOL provider [#849 @willmurphyscode] + - write info about distro EOL timing into database [#817 + @willmurphyscode] + * Additional Changes + - remove go.mod replace statement that is no longer needed + [#759 @westonsteimel] + * Dependencies + - chore(deps): update anchore dependencies (#846) + - chore: remove go.mod replace statement that is no longer + needed (#759) + - chore(deps): update tools to latest versions (#838) + - chore(deps): Bump actions/checkout from 6.0.1 to 6.0.2 (#839) + - chore(deps): Bump zizmorcore/zizmor-action from 0.3.0 to + 0.4.1 (#841) + - chore(deps): Bump actions/cache from 5.0.1 to 5.0.2 (#842) + - chore(deps): Bump actions/cache in /.github/actions/bootstrap + (#844) + - chore(deps): Bump the python-minor-and-patch group across 1 + directory with 2 updates (#840) + - chore(deps): Bump github.com/klauspost/compress from 1.18.2 + to 1.18.3 (#843) + - chore(deps): Bump boto3 in the python-minor-and-patch group + (#835) + +------------------------------------------------------------------- Old: ---- grype-db-0.48.0.obscpio New: ---- grype-db-0.49.0.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ grype-db.spec ++++++ --- /var/tmp/diff_new_pack.rgBGih/_old 2026-01-28 15:17:12.011103570 +0100 +++ /var/tmp/diff_new_pack.rgBGih/_new 2026-01-28 15:17:12.015103737 +0100 @@ -17,7 +17,7 @@ Name: grype-db -Version: 0.48.0 +Version: 0.49.0 Release: 0 Summary: A vulnerability scanner for container images and filesystems License: Apache-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.rgBGih/_old 2026-01-28 15:17:12.051105234 +0100 +++ /var/tmp/diff_new_pack.rgBGih/_new 2026-01-28 15:17:12.055105402 +0100 @@ -3,7 +3,7 @@ <param name="url">https://github.com/anchore/grype-db</param> <param name="scm">git</param> <param name="exclude">.git</param> - <param name="revision">v0.48.0</param> + <param name="revision">v0.49.0</param> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">v(.*)</param> <param name="changesgenerate">enable</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.rgBGih/_old 2026-01-28 15:17:12.083106567 +0100 +++ /var/tmp/diff_new_pack.rgBGih/_new 2026-01-28 15:17:12.087106734 +0100 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/anchore/grype-db</param> - <param name="changesrevision">919eefd67f9b1e843ae3fa6de63abb4e3aa77a8b</param></service></servicedata> + <param name="changesrevision">5629471685a768ffa129ec75b77df5a591022782</param></service></servicedata> (No newline at EOF) ++++++ grype-db-0.48.0.obscpio -> grype-db-0.49.0.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-db-0.48.0/.binny.yaml new/grype-db-0.49.0/.binny.yaml --- old/grype-db-0.48.0/.binny.yaml 2026-01-20 19:07:53.000000000 +0100 +++ new/grype-db-0.49.0/.binny.yaml 2026-01-27 17:17:39.000000000 +0100 @@ -58,7 +58,7 @@ # used for triggering a release - name: gh version: - want: v2.85.0 + want: v2.86.0 method: github-release with: repo: cli/cli diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-db-0.48.0/Makefile new/grype-db-0.49.0/Makefile --- old/grype-db-0.48.0/Makefile 2026-01-20 19:07:53.000000000 +0100 +++ new/grype-db-0.49.0/Makefile 2026-01-27 17:17:39.000000000 +0100 @@ -211,8 +211,8 @@ .PHONY: download-provider-cache download-provider-cache: - $(call title,Downloading and restoring todays "$(provider)" provider data cache) - @bash -c "$(ORAS) pull $(ORAS_FLAGS) $(GRYPE_DB_DATA_IMAGE_NAME)/$(provider):$(date) || (echo 'no data cache found for today' && exit 1)" + $(call title,Downloading and restoring "$(provider)" provider data cache ($(date))) + @bash -c "$(ORAS) pull $(ORAS_FLAGS) $(GRYPE_DB_DATA_IMAGE_NAME)/$(provider):$(date) || (echo 'no data cache found for $(date)' && exit 1)" $(GRYPE_DB) cache restore --path .cache/vunnel/$(provider)/grype-db-cache.tar.gz @rm -rf .cache/vunnel/$(provider) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-db-0.48.0/config/grype-db/publish-nightly-r2.yaml new/grype-db-0.49.0/config/grype-db/publish-nightly-r2.yaml --- old/grype-db-0.48.0/config/grype-db/publish-nightly-r2.yaml 2026-01-20 19:07:53.000000000 +0100 +++ new/grype-db-0.49.0/config/grype-db/publish-nightly-r2.yaml 2026-01-27 17:17:39.000000000 +0100 @@ -20,6 +20,7 @@ - name: chainguard-libraries - name: debian - name: echo + - name: eol - name: epss - name: github - name: kev diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-db-0.48.0/go.mod new/grype-db-0.49.0/go.mod --- old/grype-db-0.48.0/go.mod 2026-01-20 19:07:53.000000000 +0100 +++ new/grype-db-0.49.0/go.mod 2026-01-27 17:17:39.000000000 +0100 @@ -8,9 +8,9 @@ github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d github.com/adrg/xdg v0.5.3 github.com/anchore/go-logger v0.0.0-20250318195838-07ae343dd722 - github.com/anchore/grype v0.105.0 + github.com/anchore/grype v0.106.0 github.com/anchore/packageurl-go v0.1.1-0.20250220190351-d62adb6e1115 - github.com/anchore/syft v1.40.1 + github.com/anchore/syft v1.41.0 github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de github.com/dave/jennifer v1.7.1 github.com/dustin/go-humanize v1.0.1 @@ -26,7 +26,7 @@ github.com/hashicorp/go-multierror v1.1.1 github.com/iancoleman/strcase v0.3.0 github.com/jinzhu/copier v0.4.0 - github.com/klauspost/compress v1.18.2 + github.com/klauspost/compress v1.18.3 github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/mapstructure v1.5.0 github.com/openvex/go-vex v0.2.7 @@ -84,7 +84,7 @@ github.com/anchore/go-struct-converter v0.1.0 // indirect github.com/anchore/go-sync v0.0.0-20250714163430-add63db73ad1 // indirect github.com/anchore/go-version v1.2.2-0.20210903204242-51efa5b487c4 // indirect - github.com/anchore/stereoscope v0.1.18 // indirect + github.com/anchore/stereoscope v0.1.19 // indirect github.com/andybalholm/brotli v1.2.0 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/aquasecurity/go-pep440-version v0.0.1 // indirect @@ -124,7 +124,7 @@ github.com/charmbracelet/x/ansi v0.10.1 // indirect github.com/charmbracelet/x/cellbuf v0.0.13 // indirect github.com/charmbracelet/x/term v0.2.1 // indirect - github.com/clipperhouse/displaywidth v0.6.0 // indirect + github.com/clipperhouse/displaywidth v0.6.2 // indirect github.com/clipperhouse/stringish v0.1.1 // indirect github.com/clipperhouse/uax29/v2 v2.3.0 // indirect github.com/cloudflare/circl v1.6.1 // indirect @@ -147,7 +147,7 @@ github.com/deitch/magic v0.0.0-20240306090643-c67ab88f10cb // indirect github.com/diskfs/go-diskfs v1.7.0 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/cli v29.1.4+incompatible // indirect + github.com/docker/cli v29.1.5+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/docker v28.5.2+incompatible // indirect github.com/docker/docker-credential-helpers v0.9.4 // indirect @@ -164,7 +164,7 @@ github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/gabriel-vasile/mimetype v1.4.12 // indirect - github.com/github/go-spdx/v2 v2.3.5 // indirect + github.com/github/go-spdx/v2 v2.3.6 // indirect github.com/glebarez/go-sqlite v1.22.0 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.7.0 // indirect @@ -226,13 +226,13 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/muesli/termenv v0.16.0 // indirect - github.com/ncruces/go-strftime v0.1.9 // indirect + github.com/ncruces/go-strftime v1.0.0 // indirect github.com/nix-community/go-nix v0.0.0-20250101154619-4bdde671e0a1 // indirect github.com/nwaples/rardecode/v2 v2.2.0 // indirect github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect github.com/olekukonko/errors v1.1.0 // indirect - github.com/olekukonko/ll v0.1.3 // indirect - github.com/olekukonko/tablewriter v1.1.2 // indirect + github.com/olekukonko/ll v0.1.4-0.20260115111900-9e59c2286df0 // indirect + github.com/olekukonko/tablewriter v1.1.3 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect github.com/opencontainers/runtime-spec v1.3.0 // indirect @@ -262,7 +262,7 @@ github.com/sorairolake/lzip-go v0.3.8 // indirect github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect github.com/spdx/gordf v0.0.0-20250128162952-000978ccd6fb // indirect - github.com/spdx/tools-golang v0.5.6 // indirect + github.com/spdx/tools-golang v0.5.7 // indirect github.com/spf13/cast v1.10.0 // indirect github.com/spiffe/go-spiffe/v2 v2.5.0 // indirect github.com/stretchr/objx v0.5.2 // indirect @@ -293,7 +293,7 @@ go.yaml.in/yaml/v3 v3.0.4 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect golang.org/x/crypto v0.47.0 // indirect - golang.org/x/exp v0.0.0-20250711185948-6ae5c78190dc // indirect + golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect golang.org/x/mod v0.32.0 // indirect golang.org/x/net v0.49.0 // indirect golang.org/x/oauth2 v0.33.0 // indirect @@ -311,14 +311,11 @@ google.golang.org/protobuf v1.36.10 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gotest.tools/v3 v3.1.0 // indirect - modernc.org/libc v1.66.10 // indirect + modernc.org/libc v1.67.6 // indirect modernc.org/mathutil v1.7.1 // indirect modernc.org/memory v1.11.0 // indirect - modernc.org/sqlite v1.43.0 // indirect + modernc.org/sqlite v1.44.1 // indirect ) -// this is a breaking change, so we need to pin the version until glebarez/go-sqlite is updated to use internal/libc -replace modernc.org/sqlite v1.33.0 => modernc.org/sqlite v1.32.0 - // the go.mod file did not have the correct minimum go version at the time of release tagging retract v0.30.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-db-0.48.0/go.sum new/grype-db-0.49.0/go.sum --- old/grype-db-0.48.0/go.sum 2026-01-20 19:07:53.000000000 +0100 +++ new/grype-db-0.49.0/go.sum 2026-01-27 17:17:39.000000000 +0100 @@ -152,14 +152,14 @@ github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04/go.mod h1:6dK64g27Qi1qGQZ67gFmBFvEHScy0/C8qhQhNe5B5pQ= github.com/anchore/go-version v1.2.2-0.20210903204242-51efa5b487c4 h1:rmZG77uXgE+o2gozGEBoUMpX27lsku+xrMwlmBZJtbg= github.com/anchore/go-version v1.2.2-0.20210903204242-51efa5b487c4/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E= -github.com/anchore/grype v0.105.0 h1:M1VqToBkj+pwKpP7DQxtNwv7Y6kW/3jyiWalgkidtwE= -github.com/anchore/grype v0.105.0/go.mod h1:xXjcBu8CcN/yNdCCnEvN5o5PxfM11vk7V4fQp5f65qM= +github.com/anchore/grype v0.106.0 h1:mzsdv52krUw4fUVGBldkVc05rwKZ2CMts5368qXoMmQ= +github.com/anchore/grype v0.106.0/go.mod h1:RqcBZWmonvAxhmAOxqukvvAW2S6RVQdCW3/PnlaDPsc= github.com/anchore/packageurl-go v0.1.1-0.20250220190351-d62adb6e1115 h1:ZyRCmiEjnoGJZ1+Ah0ZZ/mKKqNhGcUZBl0s7PTTDzvY= github.com/anchore/packageurl-go v0.1.1-0.20250220190351-d62adb6e1115/go.mod h1:KoYIv7tdP5+CC9VGkeZV4/vGCKsY55VvoG+5dadg4YI= -github.com/anchore/stereoscope v0.1.18 h1:Mj34pRtxwfdFJkYKtKjiO9Xn7qs0RTCi59ofRYTSCEU= -github.com/anchore/stereoscope v0.1.18/go.mod h1:y8P4BURfBj0DVRly9cPHsSuZdI/AsZs3ee/x/HusEe4= -github.com/anchore/syft v1.40.1 h1:S0c/ua65y8saiJyCCZohdo7PbO0NNnaLdvD4CNfuGXE= -github.com/anchore/syft v1.40.1/go.mod h1:zgp8kzoX5ZbJzp6XLkJLk0+w7dlezKEsMak9QpfhTxQ= +github.com/anchore/stereoscope v0.1.19 h1:1G5LVmRN1Sz6qNezpVAEeN7QfWwCE9zw9TJK1ZGnkvw= +github.com/anchore/stereoscope v0.1.19/go.mod h1:+laNHlk05xA2YqgEzq8mxkFzclL3NRdeNIsiQQVeZZ4= +github.com/anchore/syft v1.41.0 h1:OyiSnf4OpkwSnDMK+9D/ZNJymtzzdZ2VokjwAmpNlrA= +github.com/anchore/syft v1.41.0/go.mod h1:vrE06rTzgwrHB3T7fh83S/M555rpxy/olUG5c+oVcoU= 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= @@ -282,8 +282,8 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/clipperhouse/displaywidth v0.6.0 h1:k32vueaksef9WIKCNcoqRNyKbyvkvkysNYnAWz2fN4s= -github.com/clipperhouse/displaywidth v0.6.0/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o= +github.com/clipperhouse/displaywidth v0.6.2 h1:ZDpTkFfpHOKte4RG5O/BOyf3ysnvFswpyYrV7z2uAKo= +github.com/clipperhouse/displaywidth v0.6.2/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o= github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs= github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA= github.com/clipperhouse/uax29/v2 v2.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4= @@ -351,8 +351,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.1.4+incompatible h1:AI8fwZhqsAsrqZnVv9h6lbexeW/LzNTasf6A4vcNN8M= -github.com/docker/cli v29.1.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v29.1.5+incompatible h1:GckbANUt3j+lsnQ6eCcQd70mNSOismSHWt8vk2AX8ao= +github.com/docker/cli v29.1.5+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= @@ -420,8 +420,8 @@ github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw= github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/github/go-spdx/v2 v2.3.5 h1:rtRQmzDSq2sU/F2oTIvNQQ+6oInq7yxex5npgY//bJQ= -github.com/github/go-spdx/v2 v2.3.5/go.mod h1:VziiWwQ/hoGS++2ifYyr/za0Ng9rlgMS+c4U7zckrDs= +github.com/github/go-spdx/v2 v2.3.6 h1:9flm625VmmTlWXi0YH5W9V8FdMfulvxalHdYnUfoqxc= +github.com/github/go-spdx/v2 v2.3.6/go.mod h1:/5rwgS0txhGtRdUZwc02bTglzg6HK3FfuEbECKlK2Sg= github.com/gkampitakis/ciinfo v0.3.2 h1:JcuOPk8ZU7nZQjdUhctuhQofk7BGHuIy0c9Ez8BNhXs= github.com/gkampitakis/ciinfo v0.3.2/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo= github.com/gkampitakis/go-snaps v0.5.19 h1:hUJlCQOpTt1M+kSisMwioDWZDWpDtdAvUhvWCx1YGW0= @@ -672,8 +672,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.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk= -github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= +github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw= +github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= @@ -788,8 +788,8 @@ github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= -github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= +github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= +github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/nix-community/go-nix v0.0.0-20250101154619-4bdde671e0a1 h1:kpt9ZfKcm+EDG4s40hMwE//d5SBgDjUOrITReV2u4aA= github.com/nix-community/go-nix v0.0.0-20250101154619-4bdde671e0a1/go.mod h1:qgCw4bBKZX8qMgGeEZzGFVT3notl42dBjNqO2jut0M0= github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249 h1:NHrXEjTNQY7P0Zfx1aMrNhpgxHmow66XQtm0aQLY0AE= @@ -800,10 +800,10 @@ github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6/go.mod h1:rEKTHC9roVVicUIfZK7DYrdIoM0EOr8mK1Hj5s3JjH0= github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM= github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= -github.com/olekukonko/ll v0.1.3 h1:sV2jrhQGq5B3W0nENUISCR6azIPf7UBUpVq0x/y70Fg= -github.com/olekukonko/ll v0.1.3/go.mod h1:b52bVQRRPObe+yyBl0TxNfhesL0nedD4Cht0/zx55Ew= -github.com/olekukonko/tablewriter v1.1.2 h1:L2kI1Y5tZBct/O/TyZK1zIE9GlBj/TVs+AY5tZDCDSc= -github.com/olekukonko/tablewriter v1.1.2/go.mod h1:z7SYPugVqGVavWoA2sGsFIoOVNmEHxUAAMrhXONtfkg= +github.com/olekukonko/ll v0.1.4-0.20260115111900-9e59c2286df0 h1:jrYnow5+hy3WRDCBypUFvVKNSPPCdqgSXIE9eJDD8LM= +github.com/olekukonko/ll v0.1.4-0.20260115111900-9e59c2286df0/go.mod h1:b52bVQRRPObe+yyBl0TxNfhesL0nedD4Cht0/zx55Ew= +github.com/olekukonko/tablewriter v1.1.3 h1:VSHhghXxrP0JHl+0NnKid7WoEmd9/urKRJLysb70nnA= +github.com/olekukonko/tablewriter v1.1.3/go.mod h1:9VU0knjhmMkXjnMKrZ3+L2JhhtsQ/L38BbL3CRNE8tM= github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= @@ -920,8 +920,8 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spdx/gordf v0.0.0-20250128162952-000978ccd6fb h1:7G2Czq97VORM5xNRrD8tSQdhoXPRs8s+Otlc7st9TS0= github.com/spdx/gordf v0.0.0-20250128162952-000978ccd6fb/go.mod h1:uKWaldnbMnjsSAXRurWqqrdyZen1R7kxl8TkmWk2OyM= -github.com/spdx/tools-golang v0.5.6 h1:HUwSJWxyAR7vBstEeZ1+guD6Jcl4TVsKyTBUwT0RjTQ= -github.com/spdx/tools-golang v0.5.6/go.mod h1:jg7w0LOpoNAw6OxKEzCoqPC2GCTj45LyTlVmXubDsYw= +github.com/spdx/tools-golang v0.5.7 h1:+sWcKGnhwp3vLdMqPcLdA6QK679vd86cK9hQWH3AwCg= +github.com/spdx/tools-golang v0.5.7/go.mod h1:jg7w0LOpoNAw6OxKEzCoqPC2GCTj45LyTlVmXubDsYw= github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= @@ -1095,8 +1095,8 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20250711185948-6ae5c78190dc h1:TS73t7x3KarrNd5qAipmspBDS1rkMcgVG/fS1aRb4Rc= -golang.org/x/exp v0.0.0-20250711185948-6ae5c78190dc/go.mod h1:A+z0yzpGtvnG90cToK5n2tu8UJVP2XUATh+r+sfOOOc= +golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY= +golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1554,18 +1554,20 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -modernc.org/cc/v4 v4.26.5 h1:xM3bX7Mve6G8K8b+T11ReenJOT+BmVqQj0FY5T4+5Y4= -modernc.org/cc/v4 v4.26.5/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= -modernc.org/ccgo/v4 v4.28.1 h1:wPKYn5EC/mYTqBO373jKjvX2n+3+aK7+sICCv4Fjy1A= -modernc.org/ccgo/v4 v4.28.1/go.mod h1:uD+4RnfrVgE6ec9NGguUNdhqzNIeeomeXf6CL0GTE5Q= +modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis= +modernc.org/cc/v4 v4.27.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= +modernc.org/ccgo/v4 v4.30.1 h1:4r4U1J6Fhj98NKfSjnPUN7Ze2c6MnAdL0hWw6+LrJpc= +modernc.org/ccgo/v4 v4.30.1/go.mod h1:bIOeI1JL54Utlxn+LwrFyjCx2n2RDiYEaJVSrgdrRfM= modernc.org/fileutil v1.3.40 h1:ZGMswMNc9JOCrcrakF1HrvmergNLAmxOPjizirpfqBA= modernc.org/fileutil v1.3.40/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc= modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= +modernc.org/gc/v3 v3.1.1 h1:k8T3gkXWY9sEiytKhcgyiZ2L0DTyCQ/nvX+LoCljoRE= +modernc.org/gc/v3 v3.1.1/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY= modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks= modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI= -modernc.org/libc v1.66.10 h1:yZkb3YeLx4oynyR+iUsXsybsX4Ubx7MQlSYEw4yj59A= -modernc.org/libc v1.66.10/go.mod h1:8vGSEwvoUoltr4dlywvHqjtAqHBaw0j1jI7iFBTAr2I= +modernc.org/libc v1.67.6 h1:eVOQvpModVLKOdT+LvBPjdQqfrZq+pC39BygcT+E7OI= +modernc.org/libc v1.67.6/go.mod h1:JAhxUVlolfYDErnwiqaLvUqc8nfb2r6S6slAgZOnaiE= modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= @@ -1574,8 +1576,8 @@ modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= -modernc.org/sqlite v1.43.0 h1:8YqiFx3G1VhHTXO2Q00bl1Wz9KhS9Q5okwfp9Y97VnA= -modernc.org/sqlite v1.43.0/go.mod h1:+VkC6v3pLOAE0A0uVucQEcbVW0I5nHCeDaBf+DpsQT8= +modernc.org/sqlite v1.44.1 h1:qybx/rNpfQipX/t47OxbHmkkJuv2JWifCMH8SVUiDas= +modernc.org/sqlite v1.44.1/go.mod h1:CzbrU2lSB1DKUusvwGz7rqEKIq+NUd8GWuBBZDs9/nA= modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-db-0.48.0/pkg/data/transformers.go new/grype-db-0.49.0/pkg/data/transformers.go --- old/grype-db-0.48.0/pkg/data/transformers.go 2026-01-20 19:07:53.000000000 +0100 +++ new/grype-db-0.49.0/pkg/data/transformers.go 2026-01-27 17:17:39.000000000 +0100 @@ -30,3 +30,4 @@ type OSVTransformerV2 func(entry unmarshal.OSVVulnerability, state provider.State) ([]Entry, error) type OpenVEXTransformerV2 func(entry unmarshal.OpenVEXVulnerability, state provider.State) ([]Entry, error) type AnnotatedOpenVEXTransformerV2 func(entry unmarshal.AnnotatedOpenVEXVulnerability, state provider.State) ([]Entry, error) +type EOLTransformerV2 func(entry unmarshal.EndOfLifeDateRelease, state provider.State) ([]Entry, error) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-db-0.48.0/pkg/process/processors/eol_processor.go new/grype-db-0.49.0/pkg/process/processors/eol_processor.go --- old/grype-db-0.48.0/pkg/process/processors/eol_processor.go 1970-01-01 01:00:00.000000000 +0100 +++ new/grype-db-0.49.0/pkg/process/processors/eol_processor.go 2026-01-27 17:17:39.000000000 +0100 @@ -0,0 +1,60 @@ +//nolint:dupl +package processors + +import ( + "io" + + "github.com/anchore/grype-db/internal/log" + "github.com/anchore/grype-db/pkg/data" + "github.com/anchore/grype-db/pkg/provider" + "github.com/anchore/grype-db/pkg/provider/unmarshal" +) + +type eolProcessor struct { + transformer data.EOLTransformerV2 +} + +func NewV2EOLProcessor(transformer data.EOLTransformerV2) data.Processor { + return &eolProcessor{ + transformer: transformer, + } +} + +func (p eolProcessor) Process(reader io.Reader, state provider.State) ([]data.Entry, error) { + var results []data.Entry + + entries, err := unmarshal.EndOfLifeDateReleaseEntries(reader) + if err != nil { + return nil, err + } + + for _, entry := range entries { + if entry.IsEmpty() { + log.Warn("dropping empty EOL entry") + continue + } + + transformedEntries, err := p.transformer(entry, state) + if err != nil { + return nil, err + } + + results = append(results, transformedEntries...) + } + + return results, nil +} + +func (p eolProcessor) IsSupported(schemaURL string) bool { + if !hasSchemaSegment(schemaURL, "eol") { + return false + } + + parsedVersion, err := parseVersion(schemaURL) + if err != nil { + log.WithFields("schema", schemaURL, "error", err).Error("failed to parse EOL schema version") + return false + } + + return parsedVersion.Major == 1 +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-db-0.48.0/pkg/process/processors/eol_processor_test.go new/grype-db-0.49.0/pkg/process/processors/eol_processor_test.go --- old/grype-db-0.48.0/pkg/process/processors/eol_processor_test.go 1970-01-01 01:00:00.000000000 +0100 +++ new/grype-db-0.49.0/pkg/process/processors/eol_processor_test.go 2026-01-27 17:17:39.000000000 +0100 @@ -0,0 +1,120 @@ +package processors + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/anchore/grype-db/pkg/data" + "github.com/anchore/grype-db/pkg/provider" + "github.com/anchore/grype-db/pkg/provider/unmarshal" +) + +func mockEOLProcessorTransform(entry unmarshal.EndOfLifeDateRelease, state provider.State) ([]data.Entry, error) { + return []data.Entry{ + { + DBSchemaVersion: 0, + Data: entry, + }, + }, nil +} + +func TestEOLProcessor_Process(t *testing.T) { + f, err := os.Open("test-fixtures/eol.json") + require.NoError(t, err) + defer f.Close() + + processor := NewV2EOLProcessor(mockEOLProcessorTransform) + entries, err := processor.Process(f, provider.State{ + Provider: "eol", + }) + + assert.NoError(t, err) + assert.Len(t, entries, 2) + + // Verify first entry is ubuntu + entry0, ok := entries[0].Data.(unmarshal.EndOfLifeDateRelease) + require.True(t, ok) + assert.Equal(t, "ubuntu", entry0.Product) + assert.Equal(t, "22.04", entry0.Name) + assert.True(t, entry0.IsLTS) + + // Verify second entry is debian + entry1, ok := entries[1].Data.(unmarshal.EndOfLifeDateRelease) + require.True(t, ok) + assert.Equal(t, "debian", entry1.Product) + assert.Equal(t, "11", entry1.Name) +} + +func TestEOLProcessor_Process_EmptyEntry(t *testing.T) { + // Test that empty entries (product == "") are filtered out + f, err := os.Open("test-fixtures/eol-with-empty.json") + require.NoError(t, err) + defer f.Close() + + processor := NewV2EOLProcessor(mockEOLProcessorTransform) + entries, err := processor.Process(f, provider.State{ + Provider: "eol", + }) + + assert.NoError(t, err) + // Should only have 1 entry (empty one filtered out) + assert.Len(t, entries, 1) + entry, ok := entries[0].Data.(unmarshal.EndOfLifeDateRelease) + require.True(t, ok) + assert.Equal(t, "alpine", entry.Product) +} + +func TestEOLProcessor_IsSupported(t *testing.T) { + tc := []struct { + name string + schemaURL string + expected bool + }{ + { + name: "valid schema URL with version 1.0.0", + schemaURL: "https://example.com/vunnel/path/eol/schema-1.0.0.json", + expected: true, + }, + { + name: "valid schema URL with version 1.2.3", + schemaURL: "https://example.com/vunnel/path/eol/schema-1.2.3.json", + expected: true, + }, + { + name: "invalid schema URL with unsupported version", + schemaURL: "https://example.com/vunnel/path/eol/schema-2.0.0.json", + expected: false, + }, + { + name: "invalid schema URL with missing version", + schemaURL: "https://example.com/vunnel/path/eol/schema.json", + expected: false, + }, + { + name: "completely invalid URL", + schemaURL: "https://example.com/invalid/schema/url", + expected: false, + }, + { + name: "invalid schema segment", + schemaURL: "https://example.com/vunnel/path/not-eol/schema-1.0.0.json", + expected: false, + }, + { + name: "epss schema should not match", + schemaURL: "https://example.com/vunnel/path/epss/schema-1.0.0.json", + expected: false, + }, + } + + p := eolProcessor{} + + for _, tt := range tc { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.expected, p.IsSupported(tt.schemaURL)) + }) + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-db-0.48.0/pkg/process/processors/test-fixtures/eol-with-empty.json new/grype-db-0.49.0/pkg/process/processors/test-fixtures/eol-with-empty.json --- old/grype-db-0.48.0/pkg/process/processors/test-fixtures/eol-with-empty.json 1970-01-01 01:00:00.000000000 +0100 +++ new/grype-db-0.49.0/pkg/process/processors/test-fixtures/eol-with-empty.json 2026-01-27 17:17:39.000000000 +0100 @@ -0,0 +1,24 @@ +[ + { + "product": "", + "identifiers": [], + "name": "", + "isEol": false, + "isMaintained": false + }, + { + "product": "alpine", + "identifiers": [], + "name": "3.18", + "codename": null, + "label": "3.18", + "releaseDate": "2023-05-09", + "isLts": false, + "ltsFrom": null, + "isEoas": false, + "eoasFrom": null, + "isEol": false, + "eolFrom": "2025-05-09", + "isMaintained": true + } +] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-db-0.48.0/pkg/process/processors/test-fixtures/eol.json new/grype-db-0.49.0/pkg/process/processors/test-fixtures/eol.json --- old/grype-db-0.48.0/pkg/process/processors/test-fixtures/eol.json 1970-01-01 01:00:00.000000000 +0100 +++ new/grype-db-0.49.0/pkg/process/processors/test-fixtures/eol.json 2026-01-27 17:17:39.000000000 +0100 @@ -0,0 +1,32 @@ +[ + { + "product": "ubuntu", + "identifiers": [], + "name": "22.04", + "codename": "Jammy Jellyfish", + "label": "22.04 LTS (Jammy Jellyfish)", + "releaseDate": "2022-04-21", + "isLts": true, + "ltsFrom": "2022-04-21", + "isEoas": false, + "eoasFrom": null, + "isEol": false, + "eolFrom": "2027-04-01", + "isMaintained": true + }, + { + "product": "debian", + "identifiers": [], + "name": "11", + "codename": "Bullseye", + "label": "11 (Bullseye)", + "releaseDate": "2021-08-14", + "isLts": false, + "ltsFrom": null, + "isEoas": false, + "eoasFrom": null, + "isEol": false, + "eolFrom": "2026-08-14", + "isMaintained": true + } +] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-db-0.48.0/pkg/process/v6/processors.go new/grype-db-0.49.0/pkg/process/v6/processors.go --- old/grype-db-0.48.0/pkg/process/v6/processors.go 2026-01-20 19:07:53.000000000 +0100 +++ new/grype-db-0.49.0/pkg/process/v6/processors.go 2026-01-27 17:17:39.000000000 +0100 @@ -5,6 +5,7 @@ "github.com/anchore/grype-db/pkg/data" "github.com/anchore/grype-db/pkg/process/processors" + "github.com/anchore/grype-db/pkg/process/v6/transformers/eol" "github.com/anchore/grype-db/pkg/process/v6/transformers/epss" "github.com/anchore/grype-db/pkg/process/v6/transformers/github" "github.com/anchore/grype-db/pkg/process/v6/transformers/kev" @@ -53,5 +54,7 @@ processors.NewV2EPSSProcessor(epss.Transform), processors.NewV2OpenVEXProcessor(openvex.Transform), processors.NewV2AnnotatedOpenVEXProcessor(openvex.AnnotatedTransform), + // EOL processor must be last to update existing OS records + processors.NewV2EOLProcessor(eol.Transform), } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-db-0.48.0/pkg/process/v6/transformers/entry.go new/grype-db-0.49.0/pkg/process/v6/transformers/entry.go --- old/grype-db-0.48.0/pkg/process/v6/transformers/entry.go 2026-01-20 19:07:53.000000000 +0100 +++ new/grype-db-0.49.0/pkg/process/v6/transformers/entry.go 2026-01-27 17:17:39.000000000 +0100 @@ -23,7 +23,8 @@ case grypeDB.VulnerabilityHandle: entry.VulnerabilityHandle = &m case grypeDB.AffectedPackageHandle, grypeDB.UnaffectedPackageHandle, grypeDB.AffectedCPEHandle, - grypeDB.UnaffectedCPEHandle, grypeDB.KnownExploitedVulnerabilityHandle, grypeDB.EpssHandle, grypeDB.CWEHandle: + grypeDB.UnaffectedCPEHandle, grypeDB.KnownExploitedVulnerabilityHandle, grypeDB.EpssHandle, grypeDB.CWEHandle, + grypeDB.OperatingSystemEOLHandle: entry.Related = append(entry.Related, m) case grypeDB.Provider: entry.Provider = &m diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-db-0.48.0/pkg/process/v6/transformers/eol/transform.go new/grype-db-0.49.0/pkg/process/v6/transformers/eol/transform.go --- old/grype-db-0.48.0/pkg/process/v6/transformers/eol/transform.go 1970-01-01 01:00:00.000000000 +0100 +++ new/grype-db-0.49.0/pkg/process/v6/transformers/eol/transform.go 2026-01-27 17:17:39.000000000 +0100 @@ -0,0 +1,128 @@ +package eol + +import ( + "strconv" + "strings" + "time" + + "github.com/anchore/grype-db/internal/log" + "github.com/anchore/grype-db/pkg/data" + "github.com/anchore/grype-db/pkg/process/v6/transformers" + "github.com/anchore/grype-db/pkg/process/v6/transformers/internal" + "github.com/anchore/grype-db/pkg/provider" + "github.com/anchore/grype-db/pkg/provider/unmarshal" + grypeDB "github.com/anchore/grype/grype/db/v6" +) + +// productNameMapping translates endoflife.date product names to grype distro names. +// Only includes mappings where the names differ. +var productNameMapping = map[string]string{ + "alpine-linux": "alpine", + "rhel": "redhat", + "amazon-linux": "amazonlinux", + "oracle-linux": "oraclelinux", + "rocky-linux": "rockylinux", + "centos-stream": "centos", // CentOS Stream is separate from classic CentOS +} + +// supportedDistros lists distros we want to import EOL data for. +// These are distros that grype tracks vulnerability data for. +var supportedDistros = map[string]bool{ + "alpine": true, + "amazonlinux": true, + "centos": true, + "debian": true, + "fedora": true, + "oraclelinux": true, + "redhat": true, + "rockylinux": true, + "almalinux": true, + "sles": true, + "ubuntu": true, + "photon": true, + "mariner": true, + "azurelinux": true, + "wolfi": true, + "chainguard": true, +} + +// Transform converts an EOL record into entries for the database. +func Transform(entry unmarshal.EndOfLifeDateRelease, state provider.State) ([]data.Entry, error) { + productName := entry.ProductName() + distroName := translateProductName(productName) + + // Skip non-distro products (software packages, frameworks, etc.) + if !supportedDistros[distroName] { + log.WithFields("product", productName).Trace("skipping non-distro EOL record") + return nil, nil + } + + handle := getOperatingSystemEOL(entry, distroName) + if handle == nil { + return nil, nil + } + + return transformers.NewEntries(*internal.ProviderModel(state), *handle), nil +} + +// translateProductName converts endoflife.date product names to grype distro names. +func translateProductName(product string) string { + if mapped, ok := productNameMapping[product]; ok { + return mapped + } + return product +} + +// getOperatingSystemEOL creates an OperatingSystemEOLHandle from an EOL record. +func getOperatingSystemEOL(entry unmarshal.EndOfLifeDateRelease, distroName string) *grypeDB.OperatingSystemEOLHandle { + // Parse version from name (e.g., "12", "22.04", "8.5") + majorVersion, minorVersion := parseVersion(entry.Name) + + // Parse EOL dates + var eolDate, eoasDate *time.Time + if entry.EOLFrom != nil { + eolDate = internal.ParseTime(*entry.EOLFrom) + } + if entry.EOASFrom != nil { + eoasDate = internal.ParseTime(*entry.EOASFrom) + } + + // Skip if no EOL data + if eolDate == nil && eoasDate == nil { + return nil + } + + // Note: We intentionally don't include codename in the handle because + // endoflife.date uses full names like "Noble Numbat" while the DB uses + // short lowercase names like "noble". Version matching is sufficient. + return &grypeDB.OperatingSystemEOLHandle{ + Name: distroName, + MajorVersion: majorVersion, + MinorVersion: minorVersion, + EOLDate: eolDate, + EOASDate: eoasDate, + } +} + +// parseVersion extracts major and minor version from a cycle string. +// Normalizes versions by stripping leading zeros (e.g., "04" -> "4") +// to match the format used in the vulnerability database. +func parseVersion(cycle string) (major, minor string) { + parts := strings.Split(cycle, ".") + if len(parts) >= 1 { + major = normalizeVersion(parts[0]) + } + if len(parts) >= 2 { + minor = normalizeVersion(parts[1]) + } + return major, minor +} + +// normalizeVersion strips leading zeros from a version string. +func normalizeVersion(v string) string { + // Try to parse as integer to strip leading zeros + if i, err := strconv.Atoi(v); err == nil { + return strconv.Itoa(i) + } + return v +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-db-0.48.0/pkg/process/v6/transformers/eol/transform_test.go new/grype-db-0.49.0/pkg/process/v6/transformers/eol/transform_test.go --- old/grype-db-0.48.0/pkg/process/v6/transformers/eol/transform_test.go 1970-01-01 01:00:00.000000000 +0100 +++ new/grype-db-0.49.0/pkg/process/v6/transformers/eol/transform_test.go 2026-01-27 17:17:39.000000000 +0100 @@ -0,0 +1,185 @@ +package eol + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestParseVersion(t *testing.T) { + tests := []struct { + name string + cycle string + wantMajor string + wantMinor string + }{ + { + name: "major only", + cycle: "12", + wantMajor: "12", + wantMinor: "", + }, + { + name: "major and minor", + cycle: "22.04", + wantMajor: "22", + wantMinor: "4", + }, + { + name: "major minor patch", + cycle: "8.5.1", + wantMajor: "8", + wantMinor: "5", + }, + { + name: "leading zero in minor", + cycle: "20.04", + wantMajor: "20", + wantMinor: "4", + }, + { + name: "leading zero in major", + cycle: "08", + wantMajor: "8", + wantMinor: "", + }, + { + name: "non-numeric version", + cycle: "bullseye", + wantMajor: "bullseye", + wantMinor: "", + }, + { + name: "mixed numeric and non-numeric", + cycle: "3.x", + wantMajor: "3", + wantMinor: "x", + }, + { + name: "empty string", + cycle: "", + wantMajor: "", + wantMinor: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotMajor, gotMinor := parseVersion(tt.cycle) + assert.Equal(t, tt.wantMajor, gotMajor, "major version mismatch") + assert.Equal(t, tt.wantMinor, gotMinor, "minor version mismatch") + }) + } +} + +func TestNormalizeVersion(t *testing.T) { + tests := []struct { + name string + version string + want string + }{ + { + name: "no leading zeros", + version: "12", + want: "12", + }, + { + name: "single leading zero", + version: "04", + want: "4", + }, + { + name: "multiple leading zeros", + version: "004", + want: "4", + }, + { + name: "zero value", + version: "0", + want: "0", + }, + { + name: "non-numeric", + version: "bullseye", + want: "bullseye", + }, + { + name: "mixed content", + version: "12a", + want: "12a", + }, + { + name: "empty string", + version: "", + want: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := normalizeVersion(tt.version) + assert.Equal(t, tt.want, got) + }) + } +} + +func TestTranslateProductName(t *testing.T) { + tests := []struct { + name string + product string + want string + }{ + { + name: "alpine-linux to alpine", + product: "alpine-linux", + want: "alpine", + }, + { + name: "rhel to redhat", + product: "rhel", + want: "redhat", + }, + { + name: "amazon-linux to amazonlinux", + product: "amazon-linux", + want: "amazonlinux", + }, + { + name: "oracle-linux to oraclelinux", + product: "oracle-linux", + want: "oraclelinux", + }, + { + name: "rocky-linux to rockylinux", + product: "rocky-linux", + want: "rockylinux", + }, + { + name: "centos-stream to centos", + product: "centos-stream", + want: "centos", + }, + { + name: "unmapped product returns as-is", + product: "debian", + want: "debian", + }, + { + name: "ubuntu returns as-is", + product: "ubuntu", + want: "ubuntu", + }, + { + name: "unknown product returns as-is", + product: "some-unknown-product", + want: "some-unknown-product", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := translateProductName(tt.product) + assert.Equal(t, tt.want, got) + }) + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-db-0.48.0/pkg/process/v6/writer.go new/grype-db-0.49.0/pkg/process/v6/writer.go --- old/grype-db-0.48.0/pkg/process/v6/writer.go 2026-01-20 19:07:53.000000000 +0100 +++ new/grype-db-0.49.0/pkg/process/v6/writer.go 2026-01-27 17:17:39.000000000 +0100 @@ -117,6 +117,8 @@ return w.store.AddEpss(&row) case grypeDB.CWEHandle: return w.store.AddCWE(&row) + case grypeDB.OperatingSystemEOLHandle: + return w.writeOperatingSystemEOL(row) default: return fmt.Errorf("data entry is not of type vulnerability, vulnerability metadata, or exclusion: %T", row) } @@ -301,3 +303,23 @@ func isFixVersion(v string) bool { return v != "" && v != "0" && strings.ToLower(v) != "none" } + +func (w *writer) writeOperatingSystemEOL(row grypeDB.OperatingSystemEOLHandle) error { + spec := grypeDB.OSSpecifier{ + Name: row.Name, + MajorVersion: row.MajorVersion, + MinorVersion: row.MinorVersion, + LabelVersion: row.Codename, + } + + updated, err := w.store.UpdateOperatingSystemEOL(spec, row.EOLDate, row.EOASDate) + if err != nil { + return fmt.Errorf("unable to update OS EOL data: %w", err) + } + + if updated == 0 { + log.WithFields("os", row.String()).Trace("no OS record found to update with EOL data") + } + + return nil +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-db-0.48.0/pkg/provider/providers/providers.go new/grype-db-0.49.0/pkg/provider/providers/providers.go --- old/grype-db-0.48.0/pkg/provider/providers/providers.go 2026-01-20 19:07:53.000000000 +0100 +++ new/grype-db-0.49.0/pkg/provider/providers/providers.go 2026-01-27 17:17:39.000000000 +0100 @@ -14,6 +14,7 @@ func New(root string, vCfg vunnel.Config, cfgs ...provider.Config) (provider.Providers, error) { var providers []provider.Provider + var eolProviders []provider.Provider if vCfg.GenerateConfigs { generatedCfgs, err := vunnel.GenerateConfigs(root, vCfg) @@ -32,14 +33,21 @@ if err != nil { return nil, err } - if p.ID().Name == "nvd" { + switch p.ID().Name { + case "nvd": // it is important that NVD is processed first since other providers depend on the severity information from these records providers = append([]provider.Provider{p}, providers...) - } else { + case "eol": + // EOL provider must run last since it needs OperatingSystem records to exist (created by other providers) + eolProviders = append(eolProviders, p) + default: providers = append(providers, p) } } + // append EOL providers at the end + providers = append(providers, eolProviders...) + return providers, nil } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-db-0.48.0/pkg/provider/unmarshal/eol.go new/grype-db-0.49.0/pkg/provider/unmarshal/eol.go --- old/grype-db-0.48.0/pkg/provider/unmarshal/eol.go 1970-01-01 01:00:00.000000000 +0100 +++ new/grype-db-0.49.0/pkg/provider/unmarshal/eol.go 2026-01-27 17:17:39.000000000 +0100 @@ -0,0 +1,94 @@ +package unmarshal + +import "io" + +// EndOfLifeDateRelease represents a single release entry from the endoflife.date API v1. +// This matches the ProductRelease schema with camelCase field names. +// Ref: https://endoflife.date/api/v1/products/{product} +// +// Note: Product and Identifiers are denormalized from the parent product by vunnel. +type EndOfLifeDateRelease struct { + // Denormalized fields added by vunnel + Product string `json:"product"` + Identifiers []EndOfLifeDateIdentifier `json:"identifiers"` + + // Fields from endoflife.date ProductRelease schema + Name string `json:"name"` + Codename *string `json:"codename"` + Label string `json:"label"` + ReleaseDate *string `json:"releaseDate"` + IsLTS bool `json:"isLts"` + LTSFrom *string `json:"ltsFrom"` + IsEOAS bool `json:"isEoas"` + EOASFrom *string `json:"eoasFrom"` + IsEOL bool `json:"isEol"` + EOLFrom *string `json:"eolFrom"` + IsMaintained bool `json:"isMaintained"` + Latest *EndOfLifeDateLatest `json:"latest"` + Custom map[string]interface{} `json:"custom"` +} + +// EndOfLifeDateLatest represents the latest release info nested within a release. +type EndOfLifeDateLatest struct { + Name string `json:"name"` + Date *string `json:"date"` + Link *string `json:"link"` +} + +// EndOfLifeDateIdentifier represents a CPE, PURL, or Repology identifier. +type EndOfLifeDateIdentifier struct { + Type string `json:"type"` + ID string `json:"id"` +} + +// EndOfLifeDateLabels contains custom labels for EOL-related dates. +type EndOfLifeDateLabels struct { + EOAS *string `json:"eoas"` + Discontinued *string `json:"discontinued"` + EOL *string `json:"eol"` + EOES *string `json:"eoes"` +} + +// EndOfLifeDateLinks contains URLs for the product. +type EndOfLifeDateLinks struct { + Icon *string `json:"icon"` + HTML *string `json:"html"` + ReleasePolicy *string `json:"releasePolicy"` +} + +// EndOfLifeDateResult represents the result object within a product response. +type EndOfLifeDateResult struct { + Name string `json:"name"` + Aliases []string `json:"aliases"` + Label string `json:"label"` + Category string `json:"category"` + Tags []string `json:"tags"` + VersionCommand *string `json:"versionCommand"` + Identifiers []EndOfLifeDateIdentifier `json:"identifiers"` + Labels EndOfLifeDateLabels `json:"labels"` + Links EndOfLifeDateLinks `json:"links"` + Releases []EndOfLifeDateRelease `json:"releases"` +} + +// EndOfLifeDateProduct represents the full product response from the endoflife.date API v1. +type EndOfLifeDateProduct struct { + SchemaVersion string `json:"schema_version"` + GeneratedAt string `json:"generated_at"` + LastModified string `json:"last_modified"` + Result EndOfLifeDateResult `json:"result"` +} + +// IsEmpty returns true if the release has no meaningful data. +func (e EndOfLifeDateRelease) IsEmpty() bool { + return e.Product == "" +} + +// ProductName returns the product name from the release. +func (e EndOfLifeDateRelease) ProductName() string { + return e.Product +} + +// EndOfLifeDateReleaseEntries unmarshals EndOfLifeDateRelease records from a reader. +func EndOfLifeDateReleaseEntries(reader io.Reader) ([]EndOfLifeDateRelease, error) { + return unmarshalSingleOrMulti[EndOfLifeDateRelease](reader) +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-db-0.48.0/uv.lock new/grype-db-0.49.0/uv.lock --- old/grype-db-0.48.0/uv.lock 2026-01-20 19:07:53.000000000 +0100 +++ new/grype-db-0.49.0/uv.lock 2026-01-27 17:17:39.000000000 +0100 @@ -4,16 +4,16 @@ [[package]] name = "boto3" -version = "1.42.26" +version = "1.42.29" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "botocore" }, { name = "jmespath" }, { name = "s3transfer" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/da/ad/06f48f2d0e9ec91d136602c7009f5f68c84be3655cc6e7e2b59aff82ead4/boto3-1.42.26.tar.gz", hash = "sha256:0fbcf1922e62d180f3644bc1139425821b38d93c1e6ec27409325d2ae86131aa", size = 112877, upload-time = "2026-01-12T20:36:39.6Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5c/24/1dd85b64004103c2e60476d0fa8d78435f5fed9db1129cd2cd332784037a/boto3-1.42.29.tar.gz", hash = "sha256:247e54f24116ad6792cfc14b274288383af3ec3433b0547da8a14a8bd6e81950", size = 112810, upload-time = "2026-01-15T20:36:39.404Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fd/0c/094a63b0ab893995b1f2e7ddb5425e11f97403feb90cea0eb770c8905487/boto3-1.42.26-py3-none-any.whl", hash = "sha256:f116cfbe7408e0a9153da363f134d2f1b5008f17ee86af104f0ce59a62be1833", size = 140576, upload-time = "2026-01-12T20:36:38.244Z" }, + { url = "https://files.pythonhosted.org/packages/51/30/2c25d7be8418e7f137ffece6097c68199dbd6996da645ec9b5a5a9647123/boto3-1.42.29-py3-none-any.whl", hash = "sha256:6c9c4dece67bf72d82ba7dff48e33a56a87cdf9b16c8887f88ca7789a95d3317", size = 140574, upload-time = "2026-01-15T20:36:37.206Z" }, ] [[package]] @@ -908,28 +908,28 @@ [[package]] name = "ruff" -version = "0.14.11" +version = "0.14.13" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d4/77/9a7fe084d268f8855d493e5031ea03fa0af8cc05887f638bf1c4e3363eb8/ruff-0.14.11.tar.gz", hash = "sha256:f6dc463bfa5c07a59b1ff2c3b9767373e541346ea105503b4c0369c520a66958", size = 5993417, upload-time = "2026-01-08T19:11:58.322Z" } +sdist = { url = "https://files.pythonhosted.org/packages/50/0a/1914efb7903174b381ee2ffeebb4253e729de57f114e63595114c8ca451f/ruff-0.14.13.tar.gz", hash = "sha256:83cd6c0763190784b99650a20fec7633c59f6ebe41c5cc9d45ee42749563ad47", size = 6059504, upload-time = "2026-01-15T20:15:16.918Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f0/a6/a4c40a5aaa7e331f245d2dc1ac8ece306681f52b636b40ef87c88b9f7afd/ruff-0.14.11-py3-none-linux_armv6l.whl", hash = "sha256:f6ff2d95cbd335841a7217bdfd9c1d2e44eac2c584197ab1385579d55ff8830e", size = 12951208, upload-time = "2026-01-08T19:12:09.218Z" }, - { url = "https://files.pythonhosted.org/packages/5c/5c/360a35cb7204b328b685d3129c08aca24765ff92b5a7efedbdd6c150d555/ruff-0.14.11-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6f6eb5c1c8033680f4172ea9c8d3706c156223010b8b97b05e82c59bdc774ee6", size = 13330075, upload-time = "2026-01-08T19:12:02.549Z" }, - { url = "https://files.pythonhosted.org/packages/1b/9e/0cc2f1be7a7d33cae541824cf3f95b4ff40d03557b575912b5b70273c9ec/ruff-0.14.11-py3-none-macosx_11_0_arm64.whl", hash = "sha256:f2fc34cc896f90080fca01259f96c566f74069a04b25b6205d55379d12a6855e", size = 12257809, upload-time = "2026-01-08T19:12:00.366Z" }, - { url = "https://files.pythonhosted.org/packages/a7/e5/5faab97c15bb75228d9f74637e775d26ac703cc2b4898564c01ab3637c02/ruff-0.14.11-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:53386375001773ae812b43205d6064dae49ff0968774e6befe16a994fc233caa", size = 12678447, upload-time = "2026-01-08T19:12:13.899Z" }, - { url = "https://files.pythonhosted.org/packages/1b/33/e9767f60a2bef779fb5855cab0af76c488e0ce90f7bb7b8a45c8a2ba4178/ruff-0.14.11-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a697737dce1ca97a0a55b5ff0434ee7205943d4874d638fe3ae66166ff46edbe", size = 12758560, upload-time = "2026-01-08T19:11:42.55Z" }, - { url = "https://files.pythonhosted.org/packages/eb/84/4c6cf627a21462bb5102f7be2a320b084228ff26e105510cd2255ea868e5/ruff-0.14.11-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6845ca1da8ab81ab1dce755a32ad13f1db72e7fba27c486d5d90d65e04d17b8f", size = 13599296, upload-time = "2026-01-08T19:11:30.371Z" }, - { url = "https://files.pythonhosted.org/packages/88/e1/92b5ed7ea66d849f6157e695dc23d5d6d982bd6aa8d077895652c38a7cae/ruff-0.14.11-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:e36ce2fd31b54065ec6f76cb08d60159e1b32bdf08507862e32f47e6dde8bcbf", size = 15048981, upload-time = "2026-01-08T19:12:04.742Z" }, - { url = "https://files.pythonhosted.org/packages/61/df/c1bd30992615ac17c2fb64b8a7376ca22c04a70555b5d05b8f717163cf9f/ruff-0.14.11-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:590bcc0e2097ecf74e62a5c10a6b71f008ad82eb97b0a0079e85defe19fe74d9", size = 14633183, upload-time = "2026-01-08T19:11:40.069Z" }, - { url = "https://files.pythonhosted.org/packages/04/e9/fe552902f25013dd28a5428a42347d9ad20c4b534834a325a28305747d64/ruff-0.14.11-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:53fe71125fc158210d57fe4da26e622c9c294022988d08d9347ec1cf782adafe", size = 14050453, upload-time = "2026-01-08T19:11:37.555Z" }, - { url = "https://files.pythonhosted.org/packages/ae/93/f36d89fa021543187f98991609ce6e47e24f35f008dfe1af01379d248a41/ruff-0.14.11-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a35c9da08562f1598ded8470fcfef2afb5cf881996e6c0a502ceb61f4bc9c8a3", size = 13757889, upload-time = "2026-01-08T19:12:07.094Z" }, - { url = "https://files.pythonhosted.org/packages/b7/9f/c7fb6ecf554f28709a6a1f2a7f74750d400979e8cd47ed29feeaa1bd4db8/ruff-0.14.11-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:0f3727189a52179393ecf92ec7057c2210203e6af2676f08d92140d3e1ee72c1", size = 13955832, upload-time = "2026-01-08T19:11:55.064Z" }, - { url = "https://files.pythonhosted.org/packages/db/a0/153315310f250f76900a98278cf878c64dfb6d044e184491dd3289796734/ruff-0.14.11-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:eb09f849bd37147a789b85995ff734a6c4a095bed5fd1608c4f56afc3634cde2", size = 12586522, upload-time = "2026-01-08T19:11:35.356Z" }, - { url = "https://files.pythonhosted.org/packages/2f/2b/a73a2b6e6d2df1d74bf2b78098be1572191e54bec0e59e29382d13c3adc5/ruff-0.14.11-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:c61782543c1231bf71041461c1f28c64b961d457d0f238ac388e2ab173d7ecb7", size = 12724637, upload-time = "2026-01-08T19:11:47.796Z" }, - { url = "https://files.pythonhosted.org/packages/f0/41/09100590320394401cd3c48fc718a8ba71c7ddb1ffd07e0ad6576b3a3df2/ruff-0.14.11-py3-none-musllinux_1_2_i686.whl", hash = "sha256:82ff352ea68fb6766140381748e1f67f83c39860b6446966cff48a315c3e2491", size = 13145837, upload-time = "2026-01-08T19:11:32.87Z" }, - { url = "https://files.pythonhosted.org/packages/3b/d8/e035db859d1d3edf909381eb8ff3e89a672d6572e9454093538fe6f164b0/ruff-0.14.11-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:728e56879df4ca5b62a9dde2dd0eb0edda2a55160c0ea28c4025f18c03f86984", size = 13850469, upload-time = "2026-01-08T19:12:11.694Z" }, - { url = "https://files.pythonhosted.org/packages/4e/02/bb3ff8b6e6d02ce9e3740f4c17dfbbfb55f34c789c139e9cd91985f356c7/ruff-0.14.11-py3-none-win32.whl", hash = "sha256:337c5dd11f16ee52ae217757d9b82a26400be7efac883e9e852646f1557ed841", size = 12851094, upload-time = "2026-01-08T19:11:45.163Z" }, - { url = "https://files.pythonhosted.org/packages/58/f1/90ddc533918d3a2ad628bc3044cdfc094949e6d4b929220c3f0eb8a1c998/ruff-0.14.11-py3-none-win_amd64.whl", hash = "sha256:f981cea63d08456b2c070e64b79cb62f951aa1305282974d4d5216e6e0178ae6", size = 14001379, upload-time = "2026-01-08T19:11:52.591Z" }, - { url = "https://files.pythonhosted.org/packages/c4/1c/1dbe51782c0e1e9cfce1d1004752672d2d4629ea46945d19d731ad772b3b/ruff-0.14.11-py3-none-win_arm64.whl", hash = "sha256:649fb6c9edd7f751db276ef42df1f3df41c38d67d199570ae2a7bd6cbc3590f0", size = 12938644, upload-time = "2026-01-08T19:11:50.027Z" }, + { url = "https://files.pythonhosted.org/packages/c3/ae/0deefbc65ca74b0ab1fd3917f94dc3b398233346a74b8bbb0a916a1a6bf6/ruff-0.14.13-py3-none-linux_armv6l.whl", hash = "sha256:76f62c62cd37c276cb03a275b198c7c15bd1d60c989f944db08a8c1c2dbec18b", size = 13062418, upload-time = "2026-01-15T20:14:50.779Z" }, + { url = "https://files.pythonhosted.org/packages/47/df/5916604faa530a97a3c154c62a81cb6b735c0cb05d1e26d5ad0f0c8ac48a/ruff-0.14.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:914a8023ece0528d5cc33f5a684f5f38199bbb566a04815c2c211d8f40b5d0ed", size = 13442344, upload-time = "2026-01-15T20:15:07.94Z" }, + { url = "https://files.pythonhosted.org/packages/4c/f3/e0e694dd69163c3a1671e102aa574a50357536f18a33375050334d5cd517/ruff-0.14.13-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d24899478c35ebfa730597a4a775d430ad0d5631b8647a3ab368c29b7e7bd063", size = 12354720, upload-time = "2026-01-15T20:15:09.854Z" }, + { url = "https://files.pythonhosted.org/packages/c3/e8/67f5fcbbaee25e8fc3b56cc33e9892eca7ffe09f773c8e5907757a7e3bdb/ruff-0.14.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9aaf3870f14d925bbaf18b8a2347ee0ae7d95a2e490e4d4aea6813ed15ebc80e", size = 12774493, upload-time = "2026-01-15T20:15:20.908Z" }, + { url = "https://files.pythonhosted.org/packages/6b/ce/d2e9cb510870b52a9565d885c0d7668cc050e30fa2c8ac3fb1fda15c083d/ruff-0.14.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac5b7f63dd3b27cc811850f5ffd8fff845b00ad70e60b043aabf8d6ecc304e09", size = 12815174, upload-time = "2026-01-15T20:15:05.74Z" }, + { url = "https://files.pythonhosted.org/packages/88/00/c38e5da58beebcf4fa32d0ddd993b63dfacefd02ab7922614231330845bf/ruff-0.14.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78d2b1097750d90ba82ce4ba676e85230a0ed694178ca5e61aa9b459970b3eb9", size = 13680909, upload-time = "2026-01-15T20:15:14.537Z" }, + { url = "https://files.pythonhosted.org/packages/61/61/cd37c9dd5bd0a3099ba79b2a5899ad417d8f3b04038810b0501a80814fd7/ruff-0.14.13-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:7d0bf87705acbbcb8d4c24b2d77fbb73d40210a95c3903b443cd9e30824a5032", size = 15144215, upload-time = "2026-01-15T20:15:22.886Z" }, + { url = "https://files.pythonhosted.org/packages/56/8a/85502d7edbf98c2df7b8876f316c0157359165e16cdf98507c65c8d07d3d/ruff-0.14.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a3eb5da8e2c9e9f13431032fdcbe7681de9ceda5835efee3269417c13f1fed5c", size = 14706067, upload-time = "2026-01-15T20:14:48.271Z" }, + { url = "https://files.pythonhosted.org/packages/7e/2f/de0df127feb2ee8c1e54354dc1179b4a23798f0866019528c938ba439aca/ruff-0.14.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:642442b42957093811cd8d2140dfadd19c7417030a7a68cf8d51fcdd5f217427", size = 14133916, upload-time = "2026-01-15T20:14:57.357Z" }, + { url = "https://files.pythonhosted.org/packages/0d/77/9b99686bb9fe07a757c82f6f95e555c7a47801a9305576a9c67e0a31d280/ruff-0.14.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4acdf009f32b46f6e8864af19cbf6841eaaed8638e65c8dac845aea0d703c841", size = 13859207, upload-time = "2026-01-15T20:14:55.111Z" }, + { url = "https://files.pythonhosted.org/packages/7d/46/2bdcb34a87a179a4d23022d818c1c236cb40e477faf0d7c9afb6813e5876/ruff-0.14.13-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:591a7f68860ea4e003917d19b5c4f5ac39ff558f162dc753a2c5de897fd5502c", size = 14043686, upload-time = "2026-01-15T20:14:52.841Z" }, + { url = "https://files.pythonhosted.org/packages/1a/a9/5c6a4f56a0512c691cf143371bcf60505ed0f0860f24a85da8bd123b2bf1/ruff-0.14.13-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:774c77e841cc6e046fc3e91623ce0903d1cd07e3a36b1a9fe79b81dab3de506b", size = 12663837, upload-time = "2026-01-15T20:15:18.921Z" }, + { url = "https://files.pythonhosted.org/packages/fe/bb/b920016ece7651fa7fcd335d9d199306665486694d4361547ccb19394c44/ruff-0.14.13-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:61f4e40077a1248436772bb6512db5fc4457fe4c49e7a94ea7c5088655dd21ae", size = 12805867, upload-time = "2026-01-15T20:14:59.272Z" }, + { url = "https://files.pythonhosted.org/packages/7d/b3/0bd909851e5696cd21e32a8fc25727e5f58f1934b3596975503e6e85415c/ruff-0.14.13-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6d02f1428357fae9e98ac7aa94b7e966fd24151088510d32cf6f902d6c09235e", size = 13208528, upload-time = "2026-01-15T20:15:03.732Z" }, + { url = "https://files.pythonhosted.org/packages/3b/3b/e2d94cb613f6bbd5155a75cbe072813756363eba46a3f2177a1fcd0cd670/ruff-0.14.13-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e399341472ce15237be0c0ae5fbceca4b04cd9bebab1a2b2c979e015455d8f0c", size = 13929242, upload-time = "2026-01-15T20:15:11.918Z" }, + { url = "https://files.pythonhosted.org/packages/6a/c5/abd840d4132fd51a12f594934af5eba1d5d27298a6f5b5d6c3be45301caf/ruff-0.14.13-py3-none-win32.whl", hash = "sha256:ef720f529aec113968b45dfdb838ac8934e519711da53a0456038a0efecbd680", size = 12919024, upload-time = "2026-01-15T20:14:43.647Z" }, + { url = "https://files.pythonhosted.org/packages/c2/55/6384b0b8ce731b6e2ade2b5449bf07c0e4c31e8a2e68ea65b3bafadcecc5/ruff-0.14.13-py3-none-win_amd64.whl", hash = "sha256:6070bd026e409734b9257e03e3ef18c6e1a216f0435c6751d7a8ec69cb59abef", size = 14097887, upload-time = "2026-01-15T20:15:01.48Z" }, + { url = "https://files.pythonhosted.org/packages/4d/e1/7348090988095e4e39560cfc2f7555b1b2a7357deba19167b600fdf5215d/ruff-0.14.13-py3-none-win_arm64.whl", hash = "sha256:7ab819e14f1ad9fe39f246cfcc435880ef7a9390d81a2b6ac7e01039083dd247", size = 13080224, upload-time = "2026-01-15T20:14:45.853Z" }, ] [[package]] ++++++ grype-db.obsinfo ++++++ --- /var/tmp/diff_new_pack.rgBGih/_old 2026-01-28 15:17:18.891389947 +0100 +++ /var/tmp/diff_new_pack.rgBGih/_new 2026-01-28 15:17:18.911390779 +0100 @@ -1,5 +1,5 @@ name: grype-db -version: 0.48.0 -mtime: 1768932473 -commit: 919eefd67f9b1e843ae3fa6de63abb4e3aa77a8b +version: 0.49.0 +mtime: 1769530659 +commit: 5629471685a768ffa129ec75b77df5a591022782 ++++++ vendor.tar.gz ++++++ /work/SRC/openSUSE:Factory/grype-db/vendor.tar.gz /work/SRC/openSUSE:Factory/.grype-db.new.1928/vendor.tar.gz differ: char 36, line 1
