Skip to content

Commit

Permalink
Support incomplete versions for a valid purl in search
Browse files Browse the repository at this point in the history
Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com>
  • Loading branch information
TG1999 committed Jan 3, 2023
1 parent 40a3974 commit f641063
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 4 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ Release notes
=============


Version v31.1.1
----------------

- We now support incomplete versions for a valid purl in search. For example,
you can now search for ``pkg:nginx/nginx@1`` and get all versions of nginx
starting with ``1``.


Version v31.1.0
----------------

Expand Down
9 changes: 5 additions & 4 deletions vulnerabilities/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
from vulnerabilities.improver import MAX_CONFIDENCE
from vulnerabilities.severity_systems import SCORING_SYSTEMS
from vulnerabilities.utils import build_vcid
from vulnerabilities.utils import remove_qualifiers_and_subpath

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -417,7 +418,8 @@ def search(self, query=None):
try:
# if it's a valid purl, use it as is
purl = PackageURL.from_string(query)
return self.for_purl(purl, with_qualifiers_and_subpath=False)
purl = str(remove_qualifiers_and_subpath(purl))
return qs.filter(package_url__istartswith=purl)
except ValueError:
return qs.filter(package_url__icontains=query)

Expand All @@ -427,10 +429,9 @@ def for_purl(self, purl, with_qualifiers_and_subpath=True):
"""
if not isinstance(purl, PackageURL):
purl = PackageURL.from_string(purl)
purl = purl_to_dict(purl)
if not with_qualifiers_and_subpath:
del purl["qualifiers"]
del purl["subpath"]
remove_qualifiers_and_subpath(purl)
purl = purl_to_dict(purl)
return self.filter(**purl)

def with_cpes(self):
Expand Down
60 changes: 60 additions & 0 deletions vulnerabilities/tests/test_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def setUp(self):
"pkg:nginx/nginx@1.14.1",
"pkg:nginx/nginx@1.0.7",
"pkg:nginx/nginx@1.0.15",
"pkg:pypi/foo@1",
]
self.packages = packages
for package in packages:
Expand Down Expand Up @@ -63,6 +64,65 @@ def test_package_view_with_purl_fragment(self):
self.assertEqual(len(pkgs), 1)
self.assertEqual(pkgs[0].purl, "pkg:nginx/nginx@1.0.15")

def test_package_view_with_purl_fragment(self):
qs = PackageSearch().get_queryset(query="nginx/nginx")
pkgs = list(qs)
pkgs = [p.purl for p in pkgs]
assert pkgs == [
"pkg:nginx/nginx@0.6.18",
"pkg:nginx/nginx@1.20.0",
"pkg:nginx/nginx@1.21.0",
"pkg:nginx/nginx@1.20.1",
"pkg:nginx/nginx@1.9.5",
"pkg:nginx/nginx@1.17.2",
"pkg:nginx/nginx@1.17.3",
"pkg:nginx/nginx@1.16.1",
"pkg:nginx/nginx@1.15.5",
"pkg:nginx/nginx@1.15.6",
"pkg:nginx/nginx@1.14.1",
"pkg:nginx/nginx@1.0.7",
"pkg:nginx/nginx@1.0.15",
]

def test_package_view_with_valid_purl_without_version(self):
qs = PackageSearch().get_queryset(query="pkg:nginx/nginx")
pkgs = list(qs)
pkgs = [p.purl for p in pkgs]
assert pkgs == [
"pkg:nginx/nginx@0.6.18",
"pkg:nginx/nginx@1.20.0",
"pkg:nginx/nginx@1.21.0",
"pkg:nginx/nginx@1.20.1",
"pkg:nginx/nginx@1.9.5",
"pkg:nginx/nginx@1.17.2",
"pkg:nginx/nginx@1.17.3",
"pkg:nginx/nginx@1.16.1",
"pkg:nginx/nginx@1.15.5",
"pkg:nginx/nginx@1.15.6",
"pkg:nginx/nginx@1.14.1",
"pkg:nginx/nginx@1.0.7",
"pkg:nginx/nginx@1.0.15",
]

def test_package_view_with_valid_purl_and_incomplete_version(self):
qs = PackageSearch().get_queryset(query="pkg:nginx/nginx@1")
pkgs = list(qs)
pkgs = [p.purl for p in pkgs]
assert pkgs == [
"pkg:nginx/nginx@1.20.0",
"pkg:nginx/nginx@1.21.0",
"pkg:nginx/nginx@1.20.1",
"pkg:nginx/nginx@1.9.5",
"pkg:nginx/nginx@1.17.2",
"pkg:nginx/nginx@1.17.3",
"pkg:nginx/nginx@1.16.1",
"pkg:nginx/nginx@1.15.5",
"pkg:nginx/nginx@1.15.6",
"pkg:nginx/nginx@1.14.1",
"pkg:nginx/nginx@1.0.7",
"pkg:nginx/nginx@1.0.15",
]


class VulnerabilitySearchTestCase(TestCase):
def setUp(self):
Expand Down
15 changes: 15 additions & 0 deletions vulnerabilities/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -420,3 +420,18 @@ def fetch_response(url):
if response.status_code == 200:
return response
raise Exception(f"Failed to fetch data from {url!r} with status code: {response.status_code!r}")


# This should be a method on PackageURL
def remove_qualifiers_and_subpath(purl):
"""
Return a package URL without qualifiers and subpath
"""
if not isinstance(purl, PackageURL):
purl = PackageURL.from_string(purl)
return PackageURL(
type=purl.type,
namespace=purl.namespace,
name=purl.name,
version=purl.version,
)

0 comments on commit f641063

Please sign in to comment.