diff --git a/vulnerabilities/api_v3.py b/vulnerabilities/api_v3.py index 75653ca2b..45461c850 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"]: @@ -81,6 +89,14 @@ class AdvisoryQuerySerializer(serializers.Serializer): default=list, ) + 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"]: raise serializers.ValidationError("purls is required") diff --git a/vulnerabilities/tests/test_api_v3.py b/vulnerabilities/tests/test_api_v3.py index c00c21354..8e3975c14 100644 --- a/vulnerabilities/tests/test_api_v3.py +++ b/vulnerabilities/tests/test_api_v3.py @@ -140,6 +140,38 @@ def test_packages_post_with_details_fixing_vulnerabilities(self): self.assertEqual(fixing_vulnerability["datasource_id"], "ghsa") self.assertEqual(pkg["next_non_vulnerable_version"], "2.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) + self.assertIn("purls", response.data) + + def test_advisories_post_with_invalid_purl(self): + url = reverse("advisory-v3-list") + + response = self.client.post( + url, + data={"purls": ["invalid-purl-scheme"]}, + format="json", + HTTP_USER_AGENT="VCIO_API_AGENT", + ) + + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertIn("purls", response.data) + def test_advisories_post(self): url = reverse("advisory-v3-list")