@@ -107,6 +107,74 @@ def parse_advisory_data(
107107 )
108108
109109
110+ def parse_advisory_data_v2 (
111+ raw_data : dict , supported_ecosystems , advisory_url : str
112+ ) -> Optional [AdvisoryData ]:
113+ """
114+ Return an AdvisoryData build from a ``raw_data`` mapping of OSV advisory and
115+ a ``supported_ecosystem`` string.
116+ """
117+ advisory_id = raw_data .get ("id" ) or ""
118+ if not advisory_id :
119+ logger .error (f"Missing advisory id in OSV data: { raw_data } " )
120+ return None
121+ summary = raw_data .get ("summary" ) or ""
122+ details = raw_data .get ("details" ) or ""
123+ summary = build_description (summary = summary , description = details )
124+ aliases = raw_data .get ("aliases" ) or []
125+
126+ date_published = get_published_date (raw_data = raw_data )
127+ severities = list (get_severities (raw_data = raw_data ))
128+ references = get_references_v2 (raw_data = raw_data )
129+
130+ affected_packages = []
131+
132+ for affected_pkg in raw_data .get ("affected" ) or []:
133+ purl = get_affected_purl (affected_pkg = affected_pkg , raw_id = advisory_id )
134+
135+ if not purl or purl .type not in supported_ecosystems :
136+ logger .error (f"Unsupported package type: { affected_pkg !r} in OSV: { advisory_id !r} " )
137+ continue
138+
139+ affected_version_range = get_affected_version_range (
140+ affected_pkg = affected_pkg ,
141+ raw_id = advisory_id ,
142+ supported_ecosystem = purl .type ,
143+ )
144+
145+ for fixed_range in affected_pkg .get ("ranges" ) or []:
146+ fixed_version = get_fixed_versions (
147+ fixed_range = fixed_range , raw_id = advisory_id , supported_ecosystem = purl .type
148+ )
149+
150+ for version in fixed_version :
151+ affected_packages .append (
152+ AffectedPackage (
153+ package = purl ,
154+ affected_version_range = affected_version_range ,
155+ fixed_version = version ,
156+ )
157+ )
158+ database_specific = raw_data .get ("database_specific" ) or {}
159+ cwe_ids = database_specific .get ("cwe_ids" ) or []
160+ weaknesses = list (map (get_cwe_id , cwe_ids ))
161+
162+ if advisory_id in aliases :
163+ aliases .remove (advisory_id )
164+
165+ return AdvisoryData (
166+ advisory_id = advisory_id ,
167+ aliases = aliases ,
168+ summary = summary ,
169+ references_v2 = references ,
170+ severities = severities ,
171+ affected_packages = affected_packages ,
172+ date_published = date_published ,
173+ weaknesses = weaknesses ,
174+ url = advisory_url ,
175+ )
176+
177+
110178def extract_fixed_versions (fixed_range ) -> Iterable [str ]:
111179 """
112180 Return a list of fixed version strings given a ``fixed_range`` mapping of
@@ -187,6 +255,23 @@ def get_references(raw_data, severities) -> List[Reference]:
187255 return references
188256
189257
258+ def get_references_v2 (raw_data ) -> List [Reference ]:
259+ """
260+ Return a list Reference extracted from a mapping of OSV ``raw_data`` given a
261+ ``severities`` list of VulnerabilitySeverity.
262+ """
263+ references = []
264+ for ref in raw_data .get ("references" ) or []:
265+ if not ref :
266+ continue
267+ url = ref ["url" ]
268+ if not url :
269+ logger .error (f"Reference without URL : { ref !r} for OSV id: { raw_data ['id' ]!r} " )
270+ continue
271+ references .append (Reference (url = ref ["url" ]))
272+ return references
273+
274+
190275def get_affected_purl (affected_pkg , raw_id ):
191276 """
192277 Return an affected PackageURL or None given a mapping of ``affected_pkg``
0 commit comments