diff --git a/scanpipe/pipes/__init__.py b/scanpipe/pipes/__init__.py index 0951bd0000..7800896943 100644 --- a/scanpipe/pipes/__init__.py +++ b/scanpipe/pipes/__init__.py @@ -33,6 +33,8 @@ from django.db.models import Count +from packageurl import PackageURL + from scanpipe.models import AbstractTaskFieldsModel from scanpipe.models import CodebaseRelation from scanpipe.models import CodebaseResource @@ -250,6 +252,14 @@ def ignore_dependency_scope(project, dependency_data): return False dependency_package_type = dependency_data.get("package_type") + if not dependency_package_type: + # Dependency data from a scancode-toolkit scan has no "package_type" + # entry: derive the type from the purl instead. + try: + purl = dependency_data.get("purl") or "" + dependency_package_type = PackageURL.from_string(purl).type + except ValueError: + dependency_package_type = None dependency_scope = dependency_data.get("scope") if dependency_package_type and dependency_scope: if dependency_scope in ignored_scope_index.get(dependency_package_type, []): diff --git a/scanpipe/tests/pipes/test_pipes.py b/scanpipe/tests/pipes/test_pipes.py index ee0ab3a88f..55556c1bf1 100644 --- a/scanpipe/tests/pipes/test_pipes.py +++ b/scanpipe/tests/pipes/test_pipes.py @@ -236,6 +236,35 @@ def test_scanpipe_pipes_update_or_create_dependency_ignored_dependency_scopes(se dependency = pipes.update_or_create_dependency(p1, dependency_data) self.assertIsNone(dependency) + def test_scanpipe_pipes_ignore_dependency_scope_package_type_from_purl(self): + # https://github.com/aboutcode-org/scancode.io/issues/2215 + # Dependency data from a scancode-toolkit scan has no "package_type" + # entry: the type must be derived from the purl. + p1 = Project.objects.create(name="Analysis") + p1.settings = { + "ignored_dependency_scopes": [ + {"package_type": "npm", "scope": "devDependencies"} + ] + } + p1.save() + + dependency_data = { + "purl": "pkg:npm/mocha@10.2.0", + "scope": "devDependencies", + } + self.assertTrue(pipes.ignore_dependency_scope(p1, dependency_data)) + + dependency_data["scope"] = "dependencies" + self.assertFalse(pipes.ignore_dependency_scope(p1, dependency_data)) + + dependency_data = {"purl": "pkg:pypi/mocha@10.2.0", "scope": "devDependencies"} + self.assertFalse(pipes.ignore_dependency_scope(p1, dependency_data)) + + # no purl and no package_type: never ignored + self.assertFalse( + pipes.ignore_dependency_scope(p1, {"scope": "devDependencies"}) + ) + def test_scanpipe_pipes_get_or_create_relation(self): p1 = Project.objects.create(name="Analysis") from1 = make_resource_file(p1, "from/a.txt")