github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/fanal/analyzer/sbom/sbom.go (about) 1 package sbom 2 3 import ( 4 "context" 5 "os" 6 "path" 7 "strings" 8 9 "golang.org/x/xerrors" 10 11 "github.com/devseccon/trivy/pkg/fanal/analyzer" 12 ftypes "github.com/devseccon/trivy/pkg/fanal/types" 13 "github.com/devseccon/trivy/pkg/sbom" 14 "github.com/devseccon/trivy/pkg/types" 15 ) 16 17 func init() { 18 analyzer.RegisterAnalyzer(&sbomAnalyzer{}) 19 } 20 21 const version = 1 22 23 var requiredSuffixes = []string{ 24 ".spdx", 25 ".spdx.json", 26 ".cdx", 27 ".cdx.json", 28 } 29 30 type sbomAnalyzer struct{} 31 32 func (a sbomAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInput) (*analyzer.AnalysisResult, error) { 33 // Format auto-detection 34 format, err := sbom.DetectFormat(input.Content) 35 if err != nil { 36 return nil, xerrors.Errorf("failed to detect SBOM format: %w", err) 37 } 38 39 bom, err := sbom.Decode(input.Content, format) 40 if err != nil { 41 return nil, xerrors.Errorf("SBOM decode error: %w", err) 42 } 43 44 // Bitnami images 45 // SPDX files are located under the /opt/bitnami/<component> directory 46 // and named with the pattern .spdx-<component>.spdx 47 // ref: https://github.com/bitnami/vulndb#how-to-consume-this-cve-feed 48 if strings.HasPrefix(input.FilePath, "opt/bitnami/") { 49 handleBitnamiImages(path.Dir(input.FilePath), bom) 50 } 51 52 return &analyzer.AnalysisResult{ 53 PackageInfos: bom.Packages, 54 Applications: bom.Applications, 55 }, nil 56 } 57 58 func (a sbomAnalyzer) Required(filePath string, _ os.FileInfo) bool { 59 for _, suffix := range requiredSuffixes { 60 if strings.HasSuffix(filePath, suffix) { 61 return true 62 } 63 } 64 return false 65 } 66 67 func (a sbomAnalyzer) Type() analyzer.Type { 68 return analyzer.TypeSBOM 69 } 70 71 func (a sbomAnalyzer) Version() int { 72 return version 73 } 74 75 func handleBitnamiImages(componentPath string, bom types.SBOM) { 76 for i, app := range bom.Applications { 77 if app.Type == ftypes.Bitnami { 78 // Set the component dir path to the application 79 bom.Applications[i].FilePath = componentPath 80 // Either Application.FilePath or Application.Libraries[].FilePath should be set 81 continue 82 } 83 84 for j, pkg := range app.Libraries { 85 // Set the absolute path since SBOM in Bitnami images contain a relative path 86 // e.g. modules/apm/elastic-apm-agent-1.36.0.jar 87 // => opt/bitnami/elasticsearch/modules/apm/elastic-apm-agent-1.36.0.jar 88 // If the file path is empty, the file path will be set to the component dir path. 89 bom.Applications[i].Libraries[j].FilePath = path.Join(componentPath, pkg.FilePath) 90 } 91 } 92 }