-
Notifications
You must be signed in to change notification settings - Fork 2.4k
/
Copy pathpackaging.go
115 lines (91 loc) · 2.63 KB
/
packaging.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package packaging
import (
"archive/zip"
"bytes"
"context"
"io"
"os"
"strings"
"golang.org/x/xerrors"
dio "github.com/aquasecurity/go-dep-parser/pkg/io"
"github.com/aquasecurity/go-dep-parser/pkg/python/packaging"
"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
"github.com/aquasecurity/trivy/pkg/fanal/analyzer/language"
"github.com/aquasecurity/trivy/pkg/fanal/types"
)
func init() {
analyzer.RegisterAnalyzer(&packagingAnalyzer{})
}
const version = 1
var (
requiredFiles = []string{
// .egg format
// https://setuptools.readthedocs.io/en/latest/deprecated/python_eggs.html#eggs-and-their-formats
".egg", // zip format
"EGG-INFO/PKG-INFO",
// .egg-info format: .egg-info can be a file or directory
// https://setuptools.readthedocs.io/en/latest/deprecated/python_eggs.html#eggs-and-their-formats
".egg-info",
".egg-info/PKG-INFO",
// wheel
".dist-info/METADATA",
}
)
type packagingAnalyzer struct{}
// Analyze analyzes egg and wheel files.
func (a packagingAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInput) (*analyzer.AnalysisResult, error) {
r := input.Content
// .egg file is zip format and PKG-INFO needs to be extracted from the zip file.
if strings.HasSuffix(input.FilePath, ".egg") {
pkginfoInZip, err := a.analyzeEggZip(input.Content, input.Info.Size())
if err != nil {
return nil, xerrors.Errorf("egg analysis error: %w", err)
}
// Egg archive may not contain required files, then we will get nil. Skip this archives
if pkginfoInZip == nil {
return nil, nil
}
r = pkginfoInZip
}
p := packaging.NewParser()
return language.AnalyzePackage(types.PythonPkg, input.FilePath, r, p, input.Options.FileChecksum)
}
func (a packagingAnalyzer) analyzeEggZip(r io.ReaderAt, size int64) (dio.ReadSeekerAt, error) {
zr, err := zip.NewReader(r, size)
if err != nil {
return nil, xerrors.Errorf("zip reader error: %w", err)
}
for _, file := range zr.File {
if !a.Required(file.Name, nil) {
continue
}
return a.open(file)
}
return nil, nil
}
func (a packagingAnalyzer) open(file *zip.File) (dio.ReadSeekerAt, error) {
f, err := file.Open()
if err != nil {
return nil, err
}
defer f.Close()
b, err := io.ReadAll(f)
if err != nil {
return nil, xerrors.Errorf("file %s open error: %w", file.Name, err)
}
return bytes.NewReader(b), nil
}
func (a packagingAnalyzer) Required(filePath string, _ os.FileInfo) bool {
for _, r := range requiredFiles {
if strings.HasSuffix(filePath, r) {
return true
}
}
return false
}
func (a packagingAnalyzer) Type() analyzer.Type {
return analyzer.TypePythonPkg
}
func (a packagingAnalyzer) Version() int {
return version
}