From ab508169e6d316b04ed3fd44780db30a03394a28 Mon Sep 17 00:00:00 2001 From: Luan Taraschi <130802253+luantaraschi@users.noreply.github.com> Date: Wed, 19 Aug 2026 11:11:10 -0300 Subject: [PATCH] fix(golang): skip remote license lookup for standard library module paths (#5192) With search-remote-licenses enabled, every module name went to the proxy, including toolchain binaries whose main module is synthesized from the package path, such as cmd/cgo. The proxy answers 404, and the direct fallback then treats the path as a repository host, producing requests like https://cmd/cgo/info/refs?service=git-upload-pack. Reuse isStandardImportPath, already in this package, to skip the remote search for paths whose first element carries no dot. Those are never publishable module paths, so neither a proxy nor a repository can resolve them. Fixes #3149 Signed-off-by: Luan Taraschi <130802253+luantaraschi@users.noreply.github.com> --- syft/pkg/cataloger/golang/licenses.go | 5 ++-- syft/pkg/cataloger/golang/licenses_test.go | 30 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/syft/pkg/cataloger/golang/licenses.go b/syft/pkg/cataloger/golang/licenses.go index cb5a67c0d..e3c40af5d 100644 --- a/syft/pkg/cataloger/golang/licenses.go +++ b/syft/pkg/cataloger/golang/licenses.go @@ -111,8 +111,9 @@ func (c *goLicenseResolver) getLicenses(ctx context.Context, resolver file.Resol } } - // download from remote sources - if c.opts.SearchRemoteLicenses { + // download from remote sources; standard library and toolchain paths are not publishable + // module paths, so neither a proxy nor a repository has anything to resolve for them + if c.opts.SearchRemoteLicenses && !isStandardImportPath(moduleName) { pkgLicenses, err = c.getLicensesFromRemote(ctx, moduleName, moduleVersion) if err != nil { log.WithFields("error", err, "module", moduleName, "version", moduleVersion).Debug("unable to read golang licenses remote") diff --git a/syft/pkg/cataloger/golang/licenses_test.go b/syft/pkg/cataloger/golang/licenses_test.go index 0674b0449..2eb9aa463 100644 --- a/syft/pkg/cataloger/golang/licenses_test.go +++ b/syft/pkg/cataloger/golang/licenses_test.go @@ -12,6 +12,7 @@ import ( "path" "path/filepath" "strings" + "sync/atomic" "testing" "github.com/stretchr/testify/require" @@ -235,6 +236,35 @@ func Test_LicenseSearch(t *testing.T) { } } +func Test_remoteLicenseSearchSkipsStandardLibrary(t *testing.T) { + ctx := pkgtest.Context(t) + + var requests atomic.Int32 + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + requests.Add(1) + w.WriteHeader(http.StatusNotFound) + })) + defer server.Close() + + // module paths whose first element carries no dot are never publishable, so there is + // nothing for a proxy or a repository to resolve + for _, moduleName := range []string{"cmd/cgo", "std", "runtime", "internal/abi", "command-line-arguments"} { + t.Run(moduleName, func(t *testing.T) { + requests.Store(0) + + l := newGoLicenseResolver("", CatalogerConfig{ + SearchRemoteLicenses: true, + Proxies: []string{server.URL}, + }) + + lics := l.getLicenses(ctx, fileresolver.Empty{}, moduleName, "(devel)") + + require.Empty(t, lics) + require.Zero(t, requests.Load(), "expected no remote lookup for a standard library module path") + }) + } +} + func Test_processCaps(t *testing.T) { tests := []struct { name string