Skip to content

Commit 5f2d91b

Browse files
committed
feat: curate non-conflicting parts of impacted package
Signed-off-by: Keshav Priyadarshi <git@keshav.space>
1 parent baec4c3 commit 5f2d91b

3 files changed

Lines changed: 454 additions & 25 deletions

File tree

vulnerabilities/pipelines/v2_importers/alpine_linux_importer.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ class AlpineLinuxImporterPipeline(VulnerableCodeBaseImporterPipelineV2):
4141
license_url = "https://secdb.alpinelinux.org/license.txt"
4242
repo_url = "git+https://github.com/aboutcode-org/aboutcode-mirror-alpine-secdb/"
4343

44+
exclude_from_package_todo = True
45+
4446
precedence = 200
4547

4648
@classmethod

vulnerabilities/pipelines/v2_improvers/compute_advisory_todo.py

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ def compute_individual_advisory_todo(self):
5151
.exclude(advisory_todos__issue_type="MISSING_SUMMARY")
5252
.exclude(advisory_todos__issue_type="MISSING_AFFECTED_PACKAGE")
5353
.exclude(advisory_todos__issue_type="MISSING_FIXED_BY_PACKAGE")
54+
.exclude(advisory_todos__issue_type="MISSING_AFFECTED_AND_FIXED_BY_PACKAGES")
5455
.prefetch_related(
5556
"impacted_packages",
5657
)
@@ -126,8 +127,6 @@ def detect_conflicting_advisories(self):
126127
AdvisoryV2.objects.exclude(
127128
advisory_todos__issue_type="MISSING_AFFECTED_AND_FIXED_BY_PACKAGES"
128129
)
129-
.exclude(advisory_todos__issue_type="MISSING_AFFECTED_PACKAGE")
130-
.exclude(advisory_todos__issue_type="MISSING_FIXED_BY_PACKAGE")
131130
.todo_excluded()
132131
.latest_per_avid()
133132
.distinct()
@@ -195,7 +194,7 @@ def detect_conflicting_advisories(self):
195194
advisory_map["fixed"].update(p.version for p in impact.fixed_by_packages.all())
196195
advisory_map["impact_count"] += 1
197196

198-
if not impact.last_successful_range_unfurl_at:
197+
if not impact.last_successful_range_unfurl_at and impact.affecting_vers:
199198
unfurled_base_purls.add(base_purl)
200199
advisories_with_unfurled_purls.add(advisory.avid)
201200

@@ -448,19 +447,21 @@ def check_conflicting_affected_and_fixed_by_packages_for_alias(
448447

449448
conflicting_advisories = list(conflicting_advisories)
450449
conflicting_avids = [avd.avid for avd in conflicting_advisories]
451-
non_conflicting_purl_avid_map = get_best_impact_for_non_conflicting_purls(
450+
best_purl_avid_impact_map = get_advisory_with_best_impact_for_purls(
452451
purl_adv_map,
453-
conflicting_package_details,
454452
conflicting_avids,
455453
)
456-
partial_merged_advisory = merged_advisory(conflicting_advisories, non_conflicting_purl_avid_map)
454+
455+
partial_merged_advisory = merged_advisory(
456+
conflicting_advisories, best_purl_avid_impact_map, conflicting_package_details
457+
)
457458
conflict_checksum = sha256_digest(canonical_value(conflicting_package_details))
458459

459460
issue_detail = {
460461
"alias": alias.alias,
461462
"conflict_checksum": conflict_checksum,
462463
"conflict_details": conflicting_package_details,
463-
"partial_merged_advisory": partial_merged_advisory,
464+
"partial_curation_advisory": partial_merged_advisory,
464465
}
465466

466467
todo_id = advisories_checksum(conflicting_advisories)
@@ -494,18 +495,14 @@ def check_conflicting_affected_and_fixed_by_packages_for_alias(
494495
return conflicting_package_count, conflicting_advisories_count
495496

496497

497-
def get_best_impact_for_non_conflicting_purls(
498-
purl_adv_map, conflicting_package_details, conflicting_avids
499-
):
498+
def get_advisory_with_best_impact_for_purls(purl_adv_map, conflicting_avids):
500499
"""
501-
Return PURL - AVID mapping for non-conflicting packages.
500+
Return PURL - AVID mapping for packages.
502501
503502
Select only one advisory per PURL based on maximum impact package count.
504503
"""
505504
best_purl_avid_map = {}
506505
for purl, advs in purl_adv_map.items():
507-
if purl in conflicting_package_details:
508-
continue
509506

510507
candidates = [
511508
(avid, values["impact_count"])
@@ -518,8 +515,8 @@ def get_best_impact_for_non_conflicting_purls(
518515
return best_purl_avid_map
519516

520517

521-
def merged_advisory(advisories, non_conflicting_purl_avid_map):
522-
"""Merge multiple advisory to one removing any duplicates or conflicting package ranges."""
518+
def merged_advisory(advisories, best_purl_avid_impact_map, conflicting_package_details):
519+
"""Merge multiple advisory to one removing any duplicates or conflicting portion of package ranges."""
523520
merged_adv = {
524521
"aliases": set(),
525522
"summary": "",
@@ -571,15 +568,31 @@ def merged_advisory(advisories, non_conflicting_purl_avid_map):
571568

572569
for affected in adv_dict.get("affected_packages", []):
573570
base_purl = PackageURL(**affected["package"]).to_string()
574-
if (
575-
base_purl in non_conflicting_purl_avid_map
576-
and non_conflicting_purl_avid_map[base_purl][0] == adv.avid
577-
):
578-
update_advisory_item(
579-
item=affected,
580-
seen_item=seen_affected,
581-
updatable=merged_adv["affected_packages"],
582-
)
571+
572+
if base_purl in best_purl_avid_impact_map:
573+
# if PURL is present in >1 advisory, then choose from best avid mapping.
574+
# if PURL is not present in best avid mapping, then it means
575+
# PURL is associated with only one advisory and can be merged as is.
576+
if best_purl_avid_impact_map[base_purl][0] != adv.avid:
577+
continue
578+
579+
if base_purl in conflicting_package_details:
580+
conflict = conflicting_package_details[base_purl]
581+
582+
if conflict["affected_disagreement"]:
583+
affected["affected_version_range"] = None
584+
585+
if conflict["fixed_disagreement"]:
586+
affected["fixed_version_range"] = None
587+
588+
if not (affected["affected_version_range"] or affected["fixed_version_range"]):
589+
continue
590+
591+
update_advisory_item(
592+
item=affected,
593+
seen_item=seen_affected,
594+
updatable=merged_adv["affected_packages"],
595+
)
583596

584597
for summary, avids in seen_summaries.values():
585598
merged_summary.append(f"{tuple(avids)}: {summary}")
@@ -588,7 +601,7 @@ def merged_advisory(advisories, non_conflicting_purl_avid_map):
588601
merged_adv["aliases"] = list(merged_adv["aliases"])
589602
merged_adv["weaknesses"] = list(merged_adv["weaknesses"])
590603

591-
merged_adv["advisory_id"] = "PLACEHOLDER_AVID"
604+
merged_adv["advisory_id"] = "PLACEHOLDER_PARTIAL_CURATION_AVID"
592605
merged_adv["date_published"] = ""
593606
merged_adv = AdvisoryDataV2.from_dict(merged_adv).to_dict()
594607

0 commit comments

Comments
 (0)