What happened:
We recently switched from scanning container images as actual container images to scanning the mounted container filesystem as a dir: (it appears to improve the problems reported in #3800).
After this switch, syft produces more entries in the files array for SPDX (or more components with type: file for CycloneDX). For SPDX, this also results in different packageVerificationCodeValue for the exact same packages.
What you expected to happen:
Same files reported when scanning the image as an image and when scanning it as a dir:, same packageVerificationCodes
Steps to reproduce the issue:
# 1. scan an image that has packages that contain hardlinked files
$ syft scan registry.fedoraproject.org/fedora-minimal:43@sha256:d028a3d86b3b68081c6610d0e77fa08a0853bb9488f522d864192c84af5b1a44 \
-o spdx-json@2.3 | jq >/tmp/fedora-minimal-image.json
# 2. scan the same image as a dir
# (if you don't have buildah, other ways to export the filesystem will work too)
$ buildah unshare -- bash -c '
set -x
container=$(buildah from registry.fedoraproject.org/fedora-minimal:43@sha256:d028a3d86b3b68081c6610d0e77fa08a0853bb9488f522d864192c84af5b1a44)
trap "buildah rm $container" EXIT
rootfs=$(buildah mount $container)
syft scan dir:$rootfs --override-default-catalogers=image -o spdx-json@2.3 | jq >/tmp/fedora-minimal-dir.json
'
# 3. see that the packageVerificationCode for e.g. glibc is different
$ jq -c < /tmp/fedora-minimal-image.json '.packages[] | select(.name == "glibc").packageVerificationCode'
{"packageVerificationCodeValue":"d601c6bf99eaa51af6783e6bd8706502c5390f0d"}
$ jq -c < /tmp/fedora-minimal-dir.json '.packages[] | select(.name == "glibc").packageVerificationCode'
{"packageVerificationCodeValue":"a3e94cf048079551f077c29a799c3522521a3acf"}
# 4. compare the files reported for glibc
$ get_glibc_files() {
local sbom=$1
jq -r '
reduce .files[] as $f ({}; .[$f.SPDXID] = $f.fileName) as $files |
(.packages[] | select(.name == "glibc")) as $glibc |
.relationships[] |
select(.spdxElementId == $glibc.SPDXID and .relationshipType == "CONTAINS") |
$files[.relatedSpdxElement]
' "$sbom" | sort
}
$ diff -u2 <(get_glibc_files /tmp/fedora-minimal-image.json) <(get_glibc_files /tmp/fedora-minimal-dir.json)
--- /proc/self/fd/12 2026-06-25 10:49:51.706356089 +0200
+++ /proc/self/fd/13 2026-06-25 10:49:51.707356075 +0200
@@ -31,4 +31,6 @@
usr/lib64/libutil.so.1
usr/libexec/getconf/POSIX_V6_LP64_OFF64
+usr/libexec/getconf/POSIX_V7_LP64_OFF64
+usr/libexec/getconf/XBS5_LP64_OFF64
usr/share/licenses/glibc/COPYING
usr/share/licenses/glibc/COPYING.LIB
# 5. see that the files reported only for dir and not for image are hardlinks
$ podman run --rm -ti registry.fedoraproject.org/fedora-minimal:43@sha256:d028a3d86b3b68081c6610d0e77fa08a0853bb9488f522d864192c84af5b1a44 \
bash -c 'stat /usr/libexec/getconf/* | grep -E "File:|Device:"'
File: /usr/libexec/getconf/POSIX_V6_LP64_OFF64
Device: 0,111 Inode: 78554226 Links: 3
File: /usr/libexec/getconf/POSIX_V7_LP64_OFF64
Device: 0,111 Inode: 78554226 Links: 3
File: /usr/libexec/getconf/XBS5_LP64_OFF64
Device: 0,111 Inode: 78554226 Links: 3
Anything else we need to know?:
The root cause seems to be that when scanning a container image, syft will only report one file per set of hardlinks pointing to the same file. When scanning a dir:, Syft reports all of the hardlinks. Because the package verification code is computed from all the files belonging to a package, this also changes the verification code value. The SPDX spec doesn't say anything about hardlinks, but the dir: approach of including hardlinks in the computation is likely more correct.
Environment:
- Output of
syft version:
Application: syft
Version: 1.45.1
BuildDate: 2026-06-05T14:21:36Z
GitCommit: d4496b05aab2d489a5c2ec606755b657229b8925
GitDescription: v1.45.1
Platform: linux/amd64
GoVersion: go1.26.3
Compiler: gc
SchemaVersion: 16.1.3
- OS (e.g:
cat /etc/os-release or similar):
NAME="Fedora Linux"
VERSION="43 (Workstation Edition)"
RELEASE_TYPE=stable
ID=fedora
VERSION_ID=43
VERSION_CODENAME=""
PRETTY_NAME="Fedora Linux 43 (Workstation Edition)"
ANSI_COLOR="0;38;2;60;110;180"
LOGO=fedora-logo-icon
CPE_NAME="cpe:/o:fedoraproject:fedora:43"
DEFAULT_HOSTNAME="fedora"
HOME_URL="https://fedoraproject.org/"
DOCUMENTATION_URL="https://docs.fedoraproject.org/en-US/fedora/f43/"
SUPPORT_URL="https://ask.fedoraproject.org/"
BUG_REPORT_URL="https://bugzilla.redhat.com/"
REDHAT_BUGZILLA_PRODUCT="Fedora"
REDHAT_BUGZILLA_PRODUCT_VERSION=43
REDHAT_SUPPORT_PRODUCT="Fedora"
REDHAT_SUPPORT_PRODUCT_VERSION=43
SUPPORT_END=2026-12-02
VARIANT="Workstation Edition"
VARIANT_ID=workstation
What happened:
We recently switched from scanning container images as actual container images to scanning the mounted container filesystem as a
dir:(it appears to improve the problems reported in #3800).After this switch, syft produces more entries in the
filesarray for SPDX (or more components withtype: filefor CycloneDX). For SPDX, this also results in differentpackageVerificationCodeValuefor the exact same packages.What you expected to happen:
Same files reported when scanning the image as an image and when scanning it as a
dir:, samepackageVerificationCodesSteps to reproduce the issue:
Anything else we need to know?:
The root cause seems to be that when scanning a container image, syft will only report one file per set of hardlinks pointing to the same file. When scanning a
dir:, Syft reports all of the hardlinks. Because the package verification code is computed from all the files belonging to a package, this also changes the verification code value. The SPDX spec doesn't say anything about hardlinks, but thedir:approach of including hardlinks in the computation is likely more correct.Environment:
syft version:cat /etc/os-releaseor similar):