77from packageurl import PackageURL
88
99from application .core .models import Branch , Observation , Product
10+ from application .core .types import OSVLinuxDistribution
1011from application .import_observations .parsers .base_parser import BaseParser
1112from application .import_observations .services .osv_cache import get_osv_vulnerability
1213from application .import_observations .types import ExtendedSemVer , Parser_Type
@@ -242,6 +243,8 @@ def _get_affected(
242243 if not package_osv_ecosystem and product .osv_linux_distribution :
243244 package_osv_ecosystem = product .osv_linux_distribution
244245
246+ package_osv_ecosystem = self ._get_linux_package_osv_ecosystem (parsed_purl , package_osv_ecosystem )
247+
245248 for affected_item in osv_vulnerability .get ("affected" , []):
246249 package = affected_item .get ("package" , {})
247250 affected_ecosystem = package .get ("ecosystem" )
@@ -251,6 +254,67 @@ def _get_affected(
251254
252255 return affected
253256
257+ def _get_linux_package_osv_ecosystem (
258+ self , parsed_purl : PackageURL , package_osv_ecosystem : Optional [str ]
259+ ) -> Optional [str ]:
260+ if not package_osv_ecosystem :
261+ package_osv_ecosystem = self ._get_linux_package_osv_ecosystem_apk (parsed_purl )
262+ if not package_osv_ecosystem :
263+ package_osv_ecosystem = self ._get_linux_package_osv_ecosystem_deb (parsed_purl )
264+ return package_osv_ecosystem
265+
266+ def _get_linux_package_osv_ecosystem_apk (self , parsed_purl : PackageURL ) -> Optional [str ]:
267+ package_osv_ecosystem = None
268+
269+ if parsed_purl .qualifiers and isinstance (parsed_purl .qualifiers , dict ):
270+ package_type = parsed_purl .type
271+ if package_type == "apk" and parsed_purl .namespace == "alpine" :
272+ distro = parsed_purl .qualifiers .get ("distro" )
273+ if distro :
274+ if distro .startswith ("alpine-" ):
275+ distro = distro [7 :]
276+ distro_parts = distro .split ("." )
277+ if len (distro_parts ) >= 2 and distro_parts [0 ].isdigit () and distro_parts [1 ].isdigit ():
278+ distro_version = f"{ distro_parts [0 ]} .{ distro_parts [1 ]} "
279+ package_osv_ecosystem = f"{ OSVLinuxDistribution .DISTRIBUTION_ALPINE } :v{ distro_version } "
280+ elif package_type == "apk" and parsed_purl .namespace == "chainguard" :
281+ package_osv_ecosystem = OSVLinuxDistribution .DISTRIBUTION_CHAINGUARD
282+ elif package_type == "apk" and parsed_purl .namespace == "wolfi" :
283+ package_osv_ecosystem = OSVLinuxDistribution .DISTRIBUTION_WOLFI
284+
285+ return package_osv_ecosystem
286+
287+ def _get_linux_package_osv_ecosystem_deb (self , parsed_purl : PackageURL ) -> Optional [str ]:
288+ package_osv_ecosystem = None
289+
290+ if parsed_purl .qualifiers and isinstance (parsed_purl .qualifiers , dict ):
291+ package_type = parsed_purl .type
292+ if package_type == "deb" and parsed_purl .namespace == "debian" :
293+ distro = parsed_purl .qualifiers .get ("distro" )
294+ if distro :
295+ if distro .startswith ("debian-" ):
296+ distro = distro [7 :]
297+ distro_parts = distro .split ("." )
298+ if len (distro_parts ) >= 1 and distro_parts [0 ].isdigit ():
299+ package_osv_ecosystem = f"{ OSVLinuxDistribution .DISTRIBUTION_DEBIAN } :{ distro_parts [0 ]} "
300+ elif package_type == "deb" and parsed_purl .namespace == "ubuntu" :
301+ distro = parsed_purl .qualifiers .get ("distro" )
302+ if distro :
303+ if distro .startswith ("ubuntu-" ):
304+ distro = distro [7 :]
305+ distro_parts = distro .split ("." )
306+ if len (distro_parts ) >= 2 :
307+ if distro_parts [0 ].isdigit () and int (distro_parts [0 ]) % 2 == 0 and distro_parts [1 ] == "04" :
308+ package_osv_ecosystem = (
309+ f"{ OSVLinuxDistribution .DISTRIBUTION_UBUNTU } :{ distro_parts [0 ]} .{ distro_parts [1 ]} :LTS"
310+ )
311+ else :
312+ package_osv_ecosystem = (
313+ f"{ OSVLinuxDistribution .DISTRIBUTION_UBUNTU } :{ distro_parts [0 ]} .{ distro_parts [1 ]} "
314+ )
315+
316+ return package_osv_ecosystem
317+
254318 def _get_package_name (self , parsed_purl : PackageURL ) -> str :
255319 package_name = parsed_purl .name
256320 package_namespace = parsed_purl .namespace
0 commit comments