github.com/anchore/syft@v1.38.2/syft/pkg/cataloger/golang/package.go (about) 1 package golang 2 3 import ( 4 "runtime/debug" 5 "strings" 6 7 "github.com/anchore/packageurl-go" 8 "github.com/anchore/syft/syft/file" 9 "github.com/anchore/syft/syft/pkg" 10 ) 11 12 func (c *goBinaryCataloger) newGoBinaryPackage(dep *debug.Module, m pkg.GolangBinaryBuildinfoEntry, licenses []pkg.License, locations ...file.Location) pkg.Package { 13 // Similar to syft/pkg/cataloger/golang/parse_go_mod.go logic - use original path for relative replacements 14 finalPath := dep.Path 15 if dep.Replace != nil { 16 if strings.HasPrefix(dep.Replace.Path, ".") || strings.HasPrefix(dep.Replace.Path, "/") { 17 finalPath = dep.Path 18 } else { 19 finalPath = dep.Replace.Path 20 } 21 dep = dep.Replace 22 } 23 24 version := dep.Version 25 if version == devel { 26 // this is a special case for the "devel" version, which is used when the module is built from source 27 // and there is no vcs tag info available. In this case, we remove the placeholder to indicate 28 // we don't know the version. 29 version = "" 30 } 31 32 p := pkg.Package{ 33 Name: finalPath, 34 Version: version, 35 Licenses: pkg.NewLicenseSet(licenses...), 36 PURL: packageURL(finalPath, version), 37 Language: pkg.Go, 38 Type: pkg.GoModulePkg, 39 Locations: file.NewLocationSet(locations...), 40 Metadata: m, 41 } 42 43 p.SetID() 44 45 return p 46 } 47 48 func newBinaryMetadata(dep *debug.Module, mainModule, goVersion, architecture string, buildSettings pkg.KeyValues, cryptoSettings, experiments []string) pkg.GolangBinaryBuildinfoEntry { 49 if dep.Replace != nil { 50 dep = dep.Replace 51 } 52 53 return pkg.GolangBinaryBuildinfoEntry{ 54 GoCompiledVersion: goVersion, 55 H1Digest: dep.Sum, 56 Architecture: architecture, 57 BuildSettings: buildSettings, 58 MainModule: mainModule, 59 GoCryptoSettings: cryptoSettings, 60 GoExperiments: experiments, 61 } 62 } 63 64 func packageURL(moduleName, moduleVersion string) string { 65 // source: https://github.com/package-url/purl-spec/blob/master/PURL-TYPES.rst#golang 66 // note: "The version is often empty when a commit is not specified and should be the commit in most cases when available." 67 68 fields := strings.Split(moduleName, "/") 69 if len(fields) == 0 { 70 return "" 71 } 72 73 namespace := "" 74 name := "" 75 // The subpath is used to point to a subpath inside a package (e.g. pkg:golang/google.golang.org/genproto#googleapis/api/annotations) 76 subpath := "" 77 78 switch len(fields) { 79 case 1: 80 name = fields[0] 81 case 2: 82 name = fields[1] 83 namespace = fields[0] 84 default: 85 name = fields[2] 86 namespace = strings.Join(fields[0:2], "/") 87 subpath = strings.Join(fields[3:], "/") 88 } 89 90 return packageurl.NewPackageURL( 91 packageurl.TypeGolang, 92 namespace, 93 name, 94 moduleVersion, 95 nil, 96 subpath, 97 ).ToString() 98 }