88#
99
1010
11+ import json
12+
1113from aboutcode .pipeline import LoopProgress
1214
1315from vulnerabilities .models import Advisory
1416from vulnerabilities .models import AdvisoryToDo
1517from vulnerabilities .models import Alias
1618from vulnerabilities .pipelines import VulnerableCodePipeline
17- from vulnerabilities .pipes import fetchcode_utils
1819from vulnerabilities .pipes .advisory import advisories_checksum
1920
2021
2122class ComputeToDo (VulnerableCodePipeline ):
22- """Compute advisory AdvisoryToDo ."""
23+ """Compute ToDos for Advisory ."""
2324
2425 pipeline_id = "compute_advisory_todo"
2526
@@ -56,7 +57,6 @@ def compute_individual_advisory_todo(self):
5657 )
5758
5859 def detect_conflicting_advisories (self ):
59- PACKAGE_VERSIONS = {}
6060 aliases = Alias .objects .filter (alias__istartswith = "cve" )
6161 aliases_count = aliases .count ()
6262
@@ -68,21 +68,12 @@ def detect_conflicting_advisories(self):
6868 progress_step = 1 ,
6969 )
7070 for alias in progress .iter (aliases .iterator (chunk_size = 2000 )):
71- advisories = (
72- Advisory .objects .filter (aliases__in = aliases )
73- .exclude (advisory_todos__issue_type = "MISSING_AFFECTED_AND_FIXED_BY_PACKAGES" )
74- .distinct ()
75- )
76- purls = get_advisories_purls (advisories = advisories )
77- get_package_versions (
78- purls = purls ,
79- package_versions = PACKAGE_VERSIONS ,
80- logger = self .log ,
81- )
71+ advisories = alias .advisories .exclude (
72+ advisory_todos__issue_type = "MISSING_AFFECTED_AND_FIXED_BY_PACKAGES"
73+ ).distinct ()
74+
8275 check_conflicting_affected_and_fixed_by_packages (
8376 advisories = advisories ,
84- package_versions = PACKAGE_VERSIONS ,
85- purls = purls ,
8677 cve = alias ,
8778 logger = self .log ,
8879 )
@@ -137,30 +128,12 @@ def check_missing_affected_and_fixed_by_packages(advisory, todo_id, logger=None)
137128 todo .advisories .add (advisory )
138129
139130
140- def get_package_versions (purls , package_versions , logger = None ):
141- for purl in purls :
142- if purl in package_versions :
143- continue
144- versions = fetchcode_utils .versions (purl = purl , logger = logger )
145- package_versions [purl ] = versions
146-
147-
148- def get_advisories_purls (advisories ):
149- purls = set ()
150- for advisory in advisories :
151- advisory_obj = advisory .to_advisory_data ()
152- purls .update ([str (i .package ) for i in advisory_obj .affected_packages ])
153- return purls
154-
155-
156- def check_conflicting_affected_and_fixed_by_packages (
157- advisories , package_versions , purls , cve , logger = None
158- ):
131+ def check_conflicting_affected_and_fixed_by_packages (advisories , cve , logger = None ):
159132 """
160133 Add appropriate AdvisoryToDo for conflicting affected/fixed packages.
161134
162135 Compute the comparison matrix for the given set of advisories. Iterate through each advisory
163- and compute and store fixed versions and normalized affected versions for each advisory,
136+ and compute and store fixed versions and affected versionrange for each advisory,
164137 keyed by purl.
165138
166139 Use the matrix to determine conflicts in affected/fixed versions for each purl. If for any purl
@@ -171,7 +144,7 @@ def check_conflicting_affected_and_fixed_by_packages(
171144 {
172145 "pkg:npm/foo/bar": {
173146 "affected": {
174- Advisory1: frozenset(NormalizedVersionRange1, NormalizedVersionRange2 ),
147+ Advisory1: frozenset(VersionRange1, VersionRange2 ),
175148 Advisory2: frozenset(...),
176149 },
177150 "fixed": {
@@ -195,11 +168,11 @@ def check_conflicting_affected_and_fixed_by_packages(
195168 matrix = {}
196169 for advisory in advisories :
197170 advisory_obj = advisory .to_advisory_data ()
171+ advisory_id = advisory .unique_content_id
198172 for affected in advisory_obj .affected_packages or []:
199- affected_purl = str (affected .package )
200-
201- if affected_purl not in purls or not purls [affected_purl ]:
173+ if not affected :
202174 continue
175+ affected_purl = str (affected .package )
203176
204177 initialize_sub_matrix (
205178 matrix = matrix ,
@@ -208,13 +181,12 @@ def check_conflicting_affected_and_fixed_by_packages(
208181 )
209182
210183 if fixed_version := affected .fixed_version :
211- matrix [affected_purl ]["fixed" ][advisory ].add (fixed_version )
184+ matrix [affected_purl ]["fixed" ][advisory_id ].add (str ( fixed_version ) )
212185
213186 if affected .affected_version_range :
214- normalized_vers = affected . affected_version_range . normalize (
215- known_versions = package_versions [ affected_purl ],
187+ matrix [ affected_purl ][ " affected" ][ advisory_id ]. add (
188+ str ( affected . affected_version_range )
216189 )
217- matrix [affected_purl ]["affected" ][advisory ].add (normalized_vers )
218190
219191 has_conflicting_affected_packages = False
220192 has_conflicting_fixed_package = False
@@ -223,22 +195,19 @@ def check_conflicting_affected_and_fixed_by_packages(
223195 fixed = board .get ("fixed" , {}).values ()
224196 affected = board .get ("affected" , {}).values ()
225197
226- # Compare affected_vers set across different advisories.
227198 unique_set_of_affected_vers = {frozenset (vers ) for vers in affected }
228-
229- # Compare fixed_version set across different advisories.
230199 unique_set_of_fixed_versions = {frozenset (versions ) for versions in fixed }
231200
232201 if len (unique_set_of_affected_vers ) > 1 :
233202 has_conflicting_affected_packages = True
203+ conflicting_affected = json .dumps (unique_set_of_affected_vers , default = list )
234204 messages .append (
235- f"{ cve } : { purl } with conflicting affected versions { unique_set_of_affected_vers } "
205+ f"{ cve } : { purl } with conflicting affected versions { conflicting_affected } "
236206 )
237207 if len (unique_set_of_fixed_versions ) > 1 :
238208 has_conflicting_fixed_package = True
239- messages .append (
240- f"{ cve } : { purl } with conflicting fixed version { unique_set_of_fixed_versions } "
241- )
209+ conflicting_fixed = json .dumps (unique_set_of_fixed_versions , default = list )
210+ messages .append (f"{ cve } : { purl } with conflicting fixed version { conflicting_fixed } " )
242211
243212 if not has_conflicting_affected_packages and not has_conflicting_fixed_package :
244213 return
@@ -249,30 +218,33 @@ def check_conflicting_affected_and_fixed_by_packages(
249218 elif not has_conflicting_affected_packages :
250219 issue_type = "CONFLICTING_FIXED_BY_PACKAGES"
251220
221+ messages .append ("Comparison matrix:" )
222+ messages .append (json .dumps (matrix , indent = 2 , default = list ))
252223 todo_id = advisories_checksum (advisories )
253224 todo , created = AdvisoryToDo .objects .get_or_create (
254225 related_advisories_id = todo_id ,
255226 issue_type = issue_type ,
256227 defaults = {
257- "issue_details " : "\n " .join (messages ),
228+ "issue_detail " : "\n " .join (messages ),
258229 },
259230 )
260231 if created :
261232 todo .advisories .add (* advisories )
262233
263234
264235def initialize_sub_matrix (matrix , affected_purl , advisory ):
236+ advisory_id = advisory .unique_content_id
265237 if affected_purl not in matrix :
266238 matrix [affected_purl ] = {
267239 "affected" : {
268- advisory : set (),
240+ advisory_id : set (),
269241 },
270242 "fixed" : {
271- advisory : set (),
243+ advisory_id : set (),
272244 },
273245 }
274246 else :
275247 if advisory not in matrix [affected_purl ]["affected" ]:
276- matrix [affected_purl ]["affected" ] = set ()
248+ matrix [affected_purl ]["affected" ][ advisory_id ] = set ()
277249 if advisory not in matrix [affected_purl ]["fixed" ]:
278- matrix [affected_purl ]["fixed" ] = set ()
250+ matrix [affected_purl ]["fixed" ][ advisory_id ] = set ()
0 commit comments