anchore / syft

CLI tool and library for generating a Software Bill of Materials from container images and filesystems
Apache License 2.0
6.12k stars 563 forks source link

Syft report panics with the golang cataloger #3037

Closed ivangonzalezacuna closed 3 months ago

ivangonzalezacuna commented 3 months ago

What happened:

Syft report panics if an image which includes Golang binaries is scanned. This behavior didn't happen in the version v1.5.0, but happened in the newer versions since the v1.6.0.

$ syft scan <IMAGE>
 ✔ Loaded image                                                                                                                                                                                                                                                                                                   <IMAGE>
 ✔ Parsed image                                                                                                                                                                                                                                                                                                               sha256:2ae065291f1a3fffc598b648bdc71a81d70a01f53cebcedd2735201f86922fbb
 ⠋ Cataloging contents             ━━━━━━━━━━━━━━━━━━━━                                                                                                                                                                                                                                                                              8643956044f9a3e2b2a4d64a5e1695bc21386a5c226e2dc06b4f36b89dd4a45e
   └── ⠋ Packages                        [678 packages]  
         └── ⠦ Go module binary cataloger      
[0053]  WARN cataloger failed cataloger=java-archive-cataloger error=unable to read files from java archive: unable to open zip archive (/tmp/syft-archive-contents-3007134279/archive-test-badbase.zip): unable to open ZipReadCloser @ "/tmp/syft-archive-contents-3007134279/archive-test-badbase.zip": zip: not a valid zip file location=/root/go/src/archive/zip/testdata/test-badbase.zip
[0053]  WARN cataloger failed cataloger=java-archive-cataloger error=unable to read files from java archive: unable to open zip archive (/tmp/syft-archive-contents-1899642132/archive-test-baddirsz.zip): unable to open ZipReadCloser @ "/tmp/syft-archive-contents-1899642132/archive-test-baddirsz.zip": zip: not a valid zip file location=/root/go/src/archive/zip/testdata/test-baddirsz.zip
A newer version of syft is available for download: 1.9.0 (installed version is 1.6.0)
failed to run tasks: 1 error occurred:
        * failed to run task: runtime error: invalid memory address or nil pointer dereference at:
goroutine 875 [running]:
runtime/debug.Stack()
        /opt/hostedtoolcache/go/1.22.3/x64/src/runtime/debug/stack.go:24 +0x5e
github.com/anchore/syft/internal/task.runTaskSafely.func1()
        /home/runner/work/syft/syft/internal/task/executor.go:67 +0x3d
panic({0x1723d40?, 0x2ca0840?})
        /opt/hostedtoolcache/go/1.22.3/x64/src/runtime/panic.go:770 +0x132
github.com/anchore/syft/syft/pkg/cataloger/golang.stdlibPackageAndRelationships({0xc01c352008?, 0x0?, 0x0?})
        /home/runner/work/syft/syft/syft/pkg/cataloger/golang/stdlib_package.go:42 +0x543
github.com/anchore/syft/syft/pkg/cataloger/golang.stdlibProcessor({0xc01c352008, 0x65, 0x92}, {0xc0105bca08, 0x4d, 0x53}, {0x0, 0x0})
        /home/runner/work/syft/syft/syft/pkg/cataloger/golang/stdlib_package.go:15 +0x57
github.com/anchore/syft/syft/pkg/cataloger/generic.processorWrapper.process({0x3a?}, {0x27ac?, 0xc002c199c0?}, {0x3a?, 0xc0153ac420?}, {0xc01c352008?, 0xc00053ee10?, 0x1f55bc8?}, {0xc0105bca08, 0x4d, ...}, ...)
        /home/runner/work/syft/syft/syft/pkg/cataloger/generic/cataloger.go:37 +0x43
github.com/anchore/syft/syft/pkg/cataloger/generic.(*Cataloger).process(...)
        /home/runner/work/syft/syft/syft/pkg/cataloger/generic/cataloger.go:184
github.com/anchore/syft/syft/pkg/cataloger/generic.(*Cataloger).Catalog(0xc00729e800, {0x1f4ca30, 0xc00053ee10}, {0x1f55bc8, 0xc00058ca50})
        /home/runner/work/syft/syft/syft/pkg/cataloger/generic/cataloger.go:179 +0x6be
github.com/anchore/syft/internal/task.NewPackageTask.func1({0x1f4ca30, 0xc00053ee10}, {0x1f55bc8, 0xc00058ca50}, {0x1f4d370, 0xc01141e390})
        /home/runner/work/syft/syft/internal/task/package_task_factory.go:103 +0x267
github.com/anchore/syft/internal/task.task.Execute(...)
        /home/runner/work/syft/syft/internal/task/task.go:64
github.com/anchore/syft/internal/task.runTaskSafely({0x1f4ca30?, 0xc00053ee10?}, {0x1f458f8?, 0xc0005958c0?}, {0x1f55bc8?, 0xc00058ca50?}, {0x1f4d370?, 0xc01141e390?})
        /home/runner/work/syft/syft/internal/task/executor.go:71 +0xa7
github.com/anchore/syft/internal/task.(*Executor).Execute.func1()
        /home/runner/work/syft/syft/internal/task/executor.go:49 +0x131
created by github.com/anchore/syft/internal/task.(*Executor).Execute in goroutine 12
        /home/runner/work/syft/syft/internal/task/executor.go:40 +0xa5

What you expected to happen:

The report to be successful and no panics are triggered at all.

Steps to reproduce the issue:

The lines that, I think, are affecting this report are the following ones from a internal Dockerfile. I will omit the other parts and keep only the important ones:

FROM maven:3.9.6-eclipse-temurin-21

RUN apt-get update && apt-get install -y python3-pip libicu70 php php-json php-xmlwriter

ADD https://go.dev/dl/go1.22.5.linux-amd64.tar.gz /tmp/go1.22.5.linux-amd64.tar.gz
RUN bash -c 'cd /tmp && sha256sum --status -c <(echo "904b924d435eaea086515bc63235b192ea441bd8c9b198c507e85009e6e4c7f0 go1.22.5.linux-amd64.tar.gz")' && \
    tar -xvf /tmp/go1.22.5.linux-amd64.tar.gz -C /tmp && \
    mv /tmp/go /root/go
ENV PATH="/root/go/bin:${PATH}"

ADD https://github.com/CycloneDX/cyclonedx-cli/releases/download/v0.25.1/cyclonedx-linux-x64 /usr/bin/cyclonedx-cli
RUN chmod +x /usr/bin/cyclonedx-cli
RUN bash -c 'cd /usr/bin && sha256sum --status -c <(echo "f7f17434b6448d735f9fd91d6f72a1364c233f78a1587941cc26e9ecf33806e7  cyclonedx-cli")'

# install
RUN pip3 install cyclonedx-bom && \
npm install -g @cyclonedx/bom@3.10.6 && \
npm install -g yarn && \
go install github.com/CycloneDX/cyclonedx-gomod/cmd/cyclonedx-gomod@v1.6.0

COPY dtrack_upload_bom.sh /usr/local/bin/
CMD bash

Anything else we need to know?:

I am pretty sure the issue was added in this Pull Request, and specifically this pointer assignment as per the panic information.

Also, by checking older issues, I believe it might be related to this issue: https://github.com/anchore/syft/issues/2736, which was solved here: https://github.com/anchore/syft/pull/2739.

Environment:

willmurphyscode commented 3 months ago

Thanks for the report @ivangonzalezacuna! I am taking a look now.

willmurphyscode commented 3 months ago

I have some more information on why this is happening. You're absolutely right that it's a nil pointer dereference at the line you pointed out.

Here's a minimal Dockerfile that reproduces the issue

FROM --platform=linux/amd64 golang:1.22.5-bookworm

RUN go install github.com/CycloneDX/cyclonedx-gomod/cmd/cyclonedx-gomod@v1.6.0

CMD bash

What's happening is that a package syft finds at /go/pkg/mod/github.com/!cyclone!d!x/cyclonedx-gomod@v1.6.0/pkg/generate/testdata/simple1.18 in that built image has a goCompiledVersion of "devel", which can't be parsed into a CPE, and so the stdlib package is nil.

I'll push a PR that at least fixes the panic, but I'll check in with the team if it makes sense to fix another way, for example by changing the CPE parsing logic to handle a Go standard lib package with the version "devel".

ivangonzalezacuna commented 3 months ago

Hi @willmurphyscode, thanks a lot for giving it a check and bring a quick fix for now! Really appreciate it :smile:

Looking forward to what the final decision with such scenarios is like. I totally agree that adding some logic to handle this "devel" packages would make sense at the end.

willmurphyscode commented 3 months ago

For now, we just won't emit a go stdlib package with the version "devel". The reason is that this version string is just not enough information to construct a meaningful package. Since which build of go stdlib might be called "devel" changes over time, without a real version number, emitting the package is incorrect or misleading.

Thanks for the detailed bug report!