diff --git a/vulnerabilities/api_v3.py b/vulnerabilities/api_v3.py index 75653ca2b..2e9b2c749 100644 --- a/vulnerabilities/api_v3.py +++ b/vulnerabilities/api_v3.py @@ -57,6 +57,14 @@ class PackageQuerySerializer(serializers.Serializer): max_advisories = serializers.IntegerField(default=100, min_value=1, max_value=10000) reachability = serializers.BooleanField(default=False) + def validate_purls(self, purls): + for purl in purls: + try: + PackageURL.from_string(purl) + except ValueError as e: + raise serializers.ValidationError(str(e)) + return purls + def validate(self, data): if not data["purls"]: if data["details"] or data["ignore_qualifiers_subpath"]: diff --git a/vulnerabilities/tests/test_api_v3.py b/vulnerabilities/tests/test_api_v3.py index c00c21354..2863706c3 100644 --- a/vulnerabilities/tests/test_api_v3.py +++ b/vulnerabilities/tests/test_api_v3.py @@ -115,6 +115,24 @@ def test_packages_post_with_details(self): pkg = response.data["results"][0] self.assertEqual(pkg["purl"], "pkg:pypi/sample@1.0.0") + def test_packages_post_with_invalid_purl(self): + url = reverse("package-v3-list") + + for ignore_qualifiers_subpath in (False, True): + with self.subTest(ignore_qualifiers_subpath=ignore_qualifiers_subpath): + response = self.client.post( + url, + data={ + "purls": ["not-a-purl"], + "details": True, + "ignore_qualifiers_subpath": ignore_qualifiers_subpath, + }, + format="json", + HTTP_USER_AGENT="VCIO_API_AGENT", + ) + + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + def test_packages_post_with_details_fixing_vulnerabilities(self): url = reverse("package-v3-list") GroupAdvisoriesForPackages().execute()