diff --git a/pkg/dependency/parser/python/poetry/parse.go b/pkg/dependency/parser/python/poetry/parse.go index e691a0cb2532..8b06942d3b6b 100644 --- a/pkg/dependency/parser/python/poetry/parse.go +++ b/pkg/dependency/parser/python/poetry/parse.go @@ -105,7 +105,7 @@ func (p *Parser) parseDependencies(deps map[string]any, pkgVersions map[string][ } func (p *Parser) parseDependency(name string, versRange any, pkgVersions map[string][]string) (string, error) { - name = normalizePkgName(name) + name = NormalizePkgName(name) vers, ok := pkgVersions[name] if !ok { return "", xerrors.Errorf("no version found for %q", name) @@ -149,9 +149,11 @@ func matchVersion(currentVersion, constraint string) (bool, error) { return c.Check(v), nil } -func normalizePkgName(name string) string { +// NormalizePkgName normalizes the package name based on pep-0426 +func NormalizePkgName(name string) string { // The package names don't use `_`, `.` or upper case, but dependency names can contain them. // We need to normalize those names. + // cf. https://peps.python.org/pep-0426/#name name = strings.ToLower(name) // e.g. https://github.com/python-poetry/poetry/blob/c8945eb110aeda611cc6721565d7ad0c657d453a/poetry.lock#L819 name = strings.ReplaceAll(name, "_", "-") // e.g. https://github.com/python-poetry/poetry/blob/c8945eb110aeda611cc6721565d7ad0c657d453a/poetry.lock#L50 name = strings.ReplaceAll(name, ".", "-") // e.g. https://github.com/python-poetry/poetry/blob/c8945eb110aeda611cc6721565d7ad0c657d453a/poetry.lock#L816 diff --git a/pkg/fanal/analyzer/language/python/poetry/poetry.go b/pkg/fanal/analyzer/language/python/poetry/poetry.go index 600f53bafc92..b16ba88481c5 100644 --- a/pkg/fanal/analyzer/language/python/poetry/poetry.go +++ b/pkg/fanal/analyzer/language/python/poetry/poetry.go @@ -8,6 +8,7 @@ import ( "os" "path/filepath" + "github.com/samber/lo" "golang.org/x/xerrors" "github.com/aquasecurity/trivy/pkg/dependency/parser/python/poetry" @@ -102,8 +103,8 @@ func (a poetryAnalyzer) mergePyProject(fsys fs.FS, dir string, app *types.Applic return xerrors.Errorf("unable to parse %s: %w", path, err) } + // Identify the direct/transitive dependencies for i, pkg := range app.Packages { - // Identify the direct/transitive dependencies if _, ok := p[pkg.Name]; ok { app.Packages[i].Relationship = types.RelationshipDirect } else { @@ -127,5 +128,11 @@ func (a poetryAnalyzer) parsePyProject(fsys fs.FS, path string) (map[string]any, if err != nil { return nil, err } + + // Packages from `pyproject.toml` can use uppercase characters, `.` and `_`. + parsed = lo.MapKeys(parsed, func(_ any, pkgName string) string { + return poetry.NormalizePkgName(pkgName) + }) + return parsed, nil } diff --git a/pkg/fanal/analyzer/language/python/poetry/testdata/happy/pyproject.toml b/pkg/fanal/analyzer/language/python/poetry/testdata/happy/pyproject.toml index 2df330973ff2..9d23492736e4 100644 --- a/pkg/fanal/analyzer/language/python/poetry/testdata/happy/pyproject.toml +++ b/pkg/fanal/analyzer/language/python/poetry/testdata/happy/pyproject.toml @@ -6,7 +6,7 @@ authors = ["Trivy"] [tool.poetry.dependencies] python = "^3.9" -flask = "^1.0" +Flask = "^1.0" requests = {version = "2.28.1", optional = true} [tool.poetry.dev-dependencies]