Skip to content

Commit 522ab6a

Browse files
committed
Add apache_httpd improver
Signed-off-by: Tushar Goel <[email protected]>
1 parent f31a2aa commit 522ab6a

File tree

2 files changed

+98
-2
lines changed

2 files changed

+98
-2
lines changed

vulnerabilities/importers/apache_httpd.py

Lines changed: 97 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,17 @@
77
# See https://aboutcode.org for more information about nexB OSS projects.
88
#
99

10-
import asyncio
10+
import logging
1111
import urllib
12+
from datetime import datetime
13+
from typing import Iterable
14+
from typing import List
15+
from typing import Mapping
16+
from typing import Optional
1217

1318
import requests
1419
from bs4 import BeautifulSoup
20+
from django.db.models.query import QuerySet
1521
from packageurl import PackageURL
1622
from univers.version_constraint import VersionConstraint
1723
from univers.version_range import ApacheVersionRange
@@ -21,8 +27,20 @@
2127
from vulnerabilities.importer import AffectedPackage
2228
from vulnerabilities.importer import Importer
2329
from vulnerabilities.importer import Reference
30+
from vulnerabilities.importer import UnMergeablePackageError
2431
from vulnerabilities.importer import VulnerabilitySeverity
32+
from vulnerabilities.improver import Improver
33+
from vulnerabilities.improver import Inference
34+
from vulnerabilities.models import Advisory
35+
from vulnerabilities.package_managers import GitHubTagsAPI
36+
from vulnerabilities.package_managers import VersionAPI
2537
from vulnerabilities.severity_systems import APACHE_HTTPD
38+
from vulnerabilities.utils import AffectedPackage as LegacyAffectedPackage
39+
from vulnerabilities.utils import get_affected_packages_by_patched_package
40+
from vulnerabilities.utils import nearest_patched_package
41+
from vulnerabilities.utils import resolve_version_range
42+
43+
logger = logging.getLogger(__name__)
2644

2745

2846
class ApacheHTTPDImporter(Importer):
@@ -147,7 +165,7 @@ def fetch_links(url):
147165
return links
148166

149167

150-
ignore_tags = {
168+
IGNORE_TAGS = {
151169
"AGB_BEFORE_AAA_CHANGES",
152170
"APACHE_1_2b1",
153171
"APACHE_1_2b10",
@@ -209,3 +227,80 @@ def fetch_links(url):
209227
"post_ajp_proxy",
210228
"pre_ajp_proxy",
211229
}
230+
231+
232+
class ApacheHTTPDImprover(Improver):
233+
def __init__(self) -> None:
234+
self.versions_fetcher_by_purl: Mapping[str, VersionAPI] = {}
235+
self.vesions_by_purl = {}
236+
237+
@property
238+
def interesting_advisories(self) -> QuerySet:
239+
return Advisory.objects.filter(created_by=ApacheHTTPDImporter.qualified_name)
240+
241+
def get_package_versions(
242+
self, package_url: PackageURL, until: Optional[datetime] = None
243+
) -> List[str]:
244+
"""
245+
Return a list of `valid_versions` for the `package_url`
246+
"""
247+
api_name = "apache/httpd"
248+
versions_fetcher = GitHubTagsAPI()
249+
return versions_fetcher.get_until(package_name=api_name, until=until).valid_versions
250+
251+
def get_inferences(self, advisory_data: AdvisoryData) -> Iterable[Inference]:
252+
"""
253+
Yield Inferences for the given advisory data
254+
"""
255+
if not advisory_data.affected_packages:
256+
return
257+
try:
258+
purl, affected_version_ranges, _ = AffectedPackage.merge(
259+
advisory_data.affected_packages
260+
)
261+
except UnMergeablePackageError:
262+
logger.error(f"Cannot merge with different purls {advisory_data.affected_packages!r}")
263+
return iter([])
264+
265+
pkg_type = purl.type
266+
pkg_namespace = purl.namespace
267+
pkg_name = purl.name
268+
269+
if not self.vesions_by_purl.get(str(purl)):
270+
valid_versions = self.get_package_versions(
271+
package_url=purl, until=advisory_data.date_published
272+
)
273+
self.vesions_by_purl[str(purl)] = valid_versions
274+
275+
valid_versions = self.vesions_by_purl[str(purl)]
276+
277+
for affected_version_range in affected_version_ranges:
278+
aff_vers, unaff_vers = resolve_version_range(
279+
affected_version_range=affected_version_range,
280+
package_versions=valid_versions,
281+
ignorable_versions=IGNORE_TAGS,
282+
)
283+
affected_purls = [
284+
PackageURL(type=pkg_type, namespace=pkg_namespace, name=pkg_name, version=version)
285+
for version in aff_vers
286+
]
287+
288+
unaffected_purls = [
289+
PackageURL(type=pkg_type, namespace=pkg_namespace, name=pkg_name, version=version)
290+
for version in unaff_vers
291+
]
292+
293+
affected_packages: List[LegacyAffectedPackage] = nearest_patched_package(
294+
vulnerable_packages=affected_purls, resolved_packages=unaffected_purls
295+
)
296+
297+
for (
298+
fixed_package,
299+
affected_packages,
300+
) in get_affected_packages_by_patched_package(affected_packages).items():
301+
yield Inference.from_advisory_data(
302+
advisory_data,
303+
confidence=100, # We are getting all valid versions to get this inference
304+
affected_purls=affected_packages,
305+
fixed_purl=fixed_package,
306+
)

vulnerabilities/improvers/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
importers.istio.IstioImprover,
2121
oval.DebianOvalBasicImprover,
2222
oval.UbuntuOvalBasicImprover,
23+
importers.apache_httpd.ApacheHTTPDImprover,
2324
]
2425

2526
IMPROVERS_REGISTRY = {x.qualified_name: x for x in IMPROVERS_REGISTRY}

0 commit comments

Comments
 (0)