Skip to content

Commit 5dabfc9

Browse files
authored
Merge pull request #1033 from TG1999/fix/1032
Handle purl fragments in package search #1032
2 parents 465a171 + 5791236 commit 5dabfc9

File tree

3 files changed

+17
-47
lines changed

3 files changed

+17
-47
lines changed

CHANGELOG.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ Version v31.1.0
77

88
- We re-enabled support for the NPM vulnerabilities advisories importer.
99
- We re-enabled support for the Retiredotnet vulnerabilities advisories importer.
10+
- We are now handling purl fragments in package search. For example:
11+
you can now serch using queries in the UI like this : `[email protected]`,
12+
`cherrypy` or `pkg:pypi`.
1013

1114

1215
Version v31.0.0

vulnerabilities/models.py

Lines changed: 8 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -412,61 +412,22 @@ def search(self, query=None):
412412
query = query and query.strip()
413413
if not query:
414414
return self.none()
415-
416415
qs = self
417-
if not query.startswith("pkg:"):
418-
# treat this as a plain search
419-
qs = qs.filter(Q(name__icontains=query) | Q(namespace__icontains=query))
420-
else:
421-
# this looks like a purl: check if it quacks like a purl
422-
purl_type = namespace = name = version = None
423-
424-
_, _scheme, remainder = query.partition("pkg:")
425-
remainder = remainder.strip()
426-
if not remainder:
427-
return qs.none()
428-
429-
try:
430-
# First, treat the query as a syntactically-correct purl
431-
purl = PackageURL.from_string(query)
432-
purl_type, namespace, name, version, _quals, _subp = purl.to_dict().values()
433-
except ValueError:
434-
# Otherwise, attempt a more lenient parsing of a possibly partial purl
435-
if "/" in remainder:
436-
purl_type, _scheme, ns_name = remainder.partition("/")
437-
ns_name = ns_name.strip()
438-
if ns_name:
439-
if "/" in ns_name:
440-
namespace, _, name = ns_name.partition("/")
441-
else:
442-
name = ns_name
443-
name = name.strip()
444-
if name:
445-
if "@" in name:
446-
name, _, version = name.partition("@")
447-
version = version.strip()
448-
name = name.strip()
449-
else:
450-
purl_type = remainder
451-
452-
if purl_type:
453-
qs = qs.filter(type__iexact=purl_type)
454-
if namespace:
455-
qs = qs.filter(namespace__iexact=namespace)
456-
if name:
457-
qs = qs.filter(name__iexact=name)
458-
if version:
459-
qs = qs.filter(version__iexact=version)
460-
461-
return qs
416+
417+
try:
418+
# if it's a valid purl, use it as is
419+
purl = PackageURL.from_string(query)
420+
return self.for_purl(purl, with_qualifiers_and_subpath=False)
421+
except ValueError:
422+
return qs.filter(package_url__icontains=query)
462423

463424
def for_purl(self, purl, with_qualifiers_and_subpath=True):
464425
"""
465426
Return a queryset matching the ``purl`` Package URL.
466427
"""
467428
if not isinstance(purl, PackageURL):
468429
purl = PackageURL.from_string(purl)
469-
purl = purl.to_dict()
430+
purl = purl_to_dict(purl)
470431
if not with_qualifiers_and_subpath:
471432
del purl["qualifiers"]
472433
del purl["subpath"]

vulnerabilities/tests/test_view.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ def test_package_view(self):
5757
self.assertEqual(len(pkgs), 1)
5858
self.assertEqual(pkgs[0].purl, "pkg:nginx/[email protected]")
5959

60+
def test_package_view_with_purl_fragment(self):
61+
qs = PackageSearch().get_queryset(query="[email protected]")
62+
pkgs = list(qs)
63+
self.assertEqual(len(pkgs), 1)
64+
self.assertEqual(pkgs[0].purl, "pkg:nginx/[email protected]")
65+
6066

6167
class VulnerabilitySearchTestCase(TestCase):
6268
def setUp(self):

0 commit comments

Comments
 (0)