def get_api_endpoint(): try: return get_service_endpoint("apiext").strip("/") except: log.warn( "Could not find valid apiext endpoint for links so will use policy engine endpoint instead" ) try: return get_service_endpoint("policy_engine").strip("/") except: log.warn( "No policy engine endpoint found either, using default but invalid url" ) return "http://<valid endpoint not found>" return ""
def _get_api_endpoint(): """ Utility function for fetching the url to external api """ try: return get_service_endpoint("apiext").strip("/") except: log.warn( "Could not find valid apiext endpoint for links so will use policy engine endpoint instead" ) try: return get_service_endpoint("policy_engine").strip("/") except: log.warn( "No policy engine endpoint found either, using default but invalid url" ) return "http://<valid endpoint not found>"
def get_url(self, servicename, base_route=None): endpt = get_service_endpoint(servicename) if base_route: return '/'.join([endpt, base_route]) else: return endpt
def evaluate(self, image_obj, context): is_fix_available = self.fix_available.value() is_vendor_only = self.vendor_only.value(default_if_none=True) comparison_idx = SEVERITY_ORDERING.index( self.severity.value(default_if_none='unknown').lower()) comparison_fn = self.SEVERITY_COMPARISONS.get( self.severity_comparison.value(default_if_none=">")) cvss_v3_base_score = self.cvss_v3_base_score.value() cvss_v3_base_score_comparison_fn = self.SEVERITY_COMPARISONS.get( self.cvss_v3_base_score_comparison.value(default_if_none=">=")) cvss_v3_exploitability_score = self.cvss_v3_exploitability_score.value( ) cvss_v3_exploitability_score_comparison_fn = self.SEVERITY_COMPARISONS.get( self.cvss_v3_exploitability_score_comparison.value( default_if_none=">=")) cvss_v3_impact_score = self.cvss_v3_impact_score.value() cvss_v3_impact_score_comparison_fn = self.SEVERITY_COMPARISONS.get( self.cvss_v3_impact_score_comparison.value(default_if_none=">=")) now = time.time() timeallowed = None if self.max_days_since_creation.value() is not None: timeallowed = now - int( int(self.max_days_since_creation.value()) * 86400) fix_timeallowed = None if self.max_days_since_fix.value() is not None: fix_timeallowed = now - int( int(self.max_days_since_fix.value()) * 86400) if not comparison_fn: pass #raise KeyError(self.severity_comparison) vendor_cvss_v3_base_score = self.vendor_cvss_v3_base_score.value() vendor_cvss_v3_base_score_comparison_fn = self.SEVERITY_COMPARISONS.get( self.vendor_cvss_v3_base_score_comparison.value( default_if_none=">=")) vendor_cvss_v3_exploitability_score = self.vendor_cvss_v3_exploitability_score.value( ) vendor_cvss_v3_exploitability_score_comparison_fn = self.SEVERITY_COMPARISONS.get( self.vendor_cvss_v3_exploitability_score_comparison.value( default_if_none=">=")) vendor_cvss_v3_impact_score = self.vendor_cvss_v3_impact_score.value() vendor_cvss_v3_impact_score_comparison_fn = self.SEVERITY_COMPARISONS.get( self.vendor_cvss_v3_impact_score_comparison.value( default_if_none=">=")) api_endpoint = None # for populating vulnerability links that point back to engine if self.package_type.value() in ['all', 'non-os']: cpevulns = context.data.get('loaded_cpe_vulnerabilities') if cpevulns: try: for sev in list(cpevulns.keys()): found_severity_idx = SEVERITY_ORDERING.index( sev.lower()) if sev else 0 if comparison_fn(found_severity_idx, comparison_idx): for image_cpe, vulnerability_cpe in cpevulns[sev]: parameter_data = OrderedDict() parameter_data['severity'] = sev.upper() parameter_data[ 'vulnerability_id'] = vulnerability_cpe.vulnerability_id parameter_data['pkg_class'] = 'non-os' parameter_data['pkg_type'] = image_cpe.pkg_type # Check if the vulnerability is too recent for this policy if timeallowed: if calendar.timegm( vulnerability_cpe.created_at. timetuple()) > timeallowed: continue parameter_data[ 'max_days_since_creation'] = vulnerability_cpe.created_at.date( ) if cvss_v3_base_score is not None: vuln_cvss_base_score = vulnerability_cpe.parent.get_max_base_score_nvd( ) if not cvss_v3_base_score_comparison_fn( vuln_cvss_base_score, cvss_v3_base_score): log.debug( "Non-OS vulnerability {} cvss V3 base score {} is not {} than policy cvss V3 base score {}, skipping" .format( vulnerability_cpe.parent.name, vuln_cvss_base_score, self. cvss_v3_base_score_comparison. value(), cvss_v3_base_score)) continue else: parameter_data[ 'cvss_v3_base_score'] = vuln_cvss_base_score if cvss_v3_exploitability_score is not None: vuln_cvss_exploitability_score = vulnerability_cpe.parent.get_max_exploitability_score_nvd( ) if not cvss_v3_exploitability_score_comparison_fn( vuln_cvss_exploitability_score, cvss_v3_exploitability_score): log.debug( "Non-OS vulnerability {} cvss V3 exploitability sub score {} is not {} than policy cvss V3 exploitability sub score {}, skipping" .format( vulnerability_cpe.parent.name, vuln_cvss_exploitability_score, self. cvss_v3_exploitability_score_comparison .value(), cvss_v3_exploitability_score)) continue else: parameter_data[ 'cvss_v3_exploitability_score'] = vuln_cvss_exploitability_score if cvss_v3_impact_score is not None: vuln_cvss_impact_score = vulnerability_cpe.parent.get_max_impact_score_nvd( ) if not cvss_v3_impact_score_comparison_fn( vuln_cvss_impact_score, cvss_v3_impact_score): log.debug( "Non-OS vulnerability {} cvss V3 impact sub score {} is not {} than policy cvss V3 impact score {}, skipping" .format( vulnerability_cpe.parent.name, vuln_cvss_impact_score, self. cvss_v3_impact_score_comparison .value(), cvss_v3_impact_score)) continue else: parameter_data[ 'cvss_v3_impact_score'] = vuln_cvss_impact_score trigger_fname = None if image_cpe.pkg_type in ['java', 'gem']: try: trigger_fname = image_cpe.pkg_path.split( "/")[-1] except: trigger_fname = None elif image_cpe.pkg_type in ['npm']: try: trigger_fname = image_cpe.pkg_path.split( "/")[-2] except: trigger_fname = None if not trigger_fname: trigger_fname = "-".join( [image_cpe.name, image_cpe.version]) if is_fix_available is not None: # Must do a fix_available check fix_available_in = vulnerability_cpe.get_fixed_in( ) # explicit fix state check matches fix availability if is_fix_available == ( fix_available_in is not None and len(fix_available_in) > 0): if is_fix_available: parameter_data[ 'fixed_version'] = ', '.join( fix_available_in) else: # if_fix_available is set but does not match is_fix_available check continue if is_fix_available and fix_timeallowed is not None: if fix_available_in: if calendar.timegm( vulnerability_cpe. created_at.timetuple( )) > fix_timeallowed: continue else: parameter_data[ 'max_days_since_fix'] = vulnerability_cpe.created_at.date( ) if not vulnerability_cpe.parent.link: if not api_endpoint: api_endpoint = get_service_endpoint( 'apiext').strip('/') parameter_data[ 'link'] = '{}/query/vulnerabilities?id={}'.format( api_endpoint, vulnerability_cpe.vulnerability_id) else: parameter_data[ 'link'] = vulnerability_cpe.parent.link fix_msg = '' if parameter_data.get('fixed_version', None): fix_msg = "(fixed in: {})".format( parameter_data.get('fixed_version')) score_msg = '' score_tuples = [] for s in [ 'cvss_v3_base_score', 'cvss_v3_exploitability_score', 'cvss_v3_impact_score' ]: if parameter_data.get(s, None): score_tuples.append("{}={}".format( s, parameter_data.get(s))) if score_tuples: score_msg = "({})".format( ' '.join(score_tuples)) time_msg = '' time_tuples = [] for s in [ 'max_days_since_creation', 'max_days_since_fix' ]: if parameter_data.get(s, None): time_tuples.append("{}={}".format( s, parameter_data.get(s))) if time_tuples: time_msg = "({})".format( ' '.join(time_tuples)) if vendor_cvss_v3_base_score is not None: vuln_vendor_cvss_base_score = vulnerability_cpe.parent.get_max_base_score_vendor( ) if not vendor_cvss_v3_base_score_comparison_fn( vuln_vendor_cvss_base_score, vendor_cvss_v3_base_score): log.debug( "Non-OS vulnerability {} vendor cvss V3 base score {} is not {} than policy vendor cvss V3 base score {}, skipping" .format( vulnerability_cpe.parent.name, vuln_vendor_cvss_base_score, self. vendor_cvss_v3_base_score_comparison .value(), vendor_cvss_v3_base_score)) continue else: parameter_data[ 'vendor_cvss_v3_base_score'] = vuln_vendor_cvss_base_score if vendor_cvss_v3_exploitability_score is not None: vuln_vendor_cvss_exploitability_score = vulnerability_cpe.parent.get_max_exploitability_score_vendor( ) if not vendor_cvss_v3_exploitability_score_comparison_fn( vuln_vendor_cvss_exploitability_score, vendor_cvss_v3_exploitability_score ): log.debug( "Non-OS vulnerability {} vendor cvss V3 exploitability sub score {} is not {} than policy vendor cvss V3 exploitability sub score {}, skipping" .format( vulnerability_cpe.parent.name, vuln_vendor_cvss_exploitability_score, self. vendor_cvss_v3_exploitability_score_comparison .value(), vendor_cvss_v3_exploitability_score )) continue else: parameter_data[ 'vendor_cvss_v3_exploitability_score'] = vuln_vendor_cvss_exploitability_score if vendor_cvss_v3_impact_score is not None: vuln_vendor_cvss_impact_score = vulnerability_cpe.parent.get_max_impact_score_vendor( ) if not vendor_cvss_v3_impact_score_comparison_fn( vuln_vendor_cvss_impact_score, vendor_cvss_v3_impact_score): log.debug( "Non-OS vulnerability {} vendor cvss V3 impact sub score {} is not {} than policy vendor cvss V3 impact score {}, skipping" .format( vulnerability_cpe.parent.name, vuln_vendor_cvss_impact_score, self. vendor_cvss_v3_impact_score_comparison .value(), vendor_cvss_v3_impact_score)) continue else: parameter_data[ 'vendor_cvss_v3_impact_score'] = vuln_vendor_cvss_impact_score vendor_score_msg = '' vendor_score_tuples = [] for s in [ 'vendor_cvss_v3_base_score', 'vendor_cvss_v3_exploitability_score', 'vendor_cvss_v3_impact_score' ]: if parameter_data.get(s, None): vendor_score_tuples.append( "{}={}".format( s, parameter_data.get(s))) if vendor_score_tuples: vendor_score_msg = "({})".format( ' '.join(vendor_score_tuples)) # new detail message approach #pkgname = image_cpe.pkg_path #msg = "Vulnerability found in package {} - matching parameters: ".format(pkgname) #for i in parameter_data: # msg += "{}={} ".format(i, parameter_data[i]) pkgname = image_cpe.pkg_path msg = "{} Vulnerability found in {} package type ({}) - {} {}{}{}{}({} - {})".format( parameter_data['severity'].upper(), parameter_data['pkg_class'], parameter_data['pkg_type'], pkgname, fix_msg, score_msg, time_msg, vendor_score_msg, parameter_data['vulnerability_id'], parameter_data['link']) self._fire(instance_id=vulnerability_cpe. vulnerability_id + '+' + trigger_fname, msg=msg) except Exception as err: log.warn( "problem during non-os vulnerability evaluation - exception: {}" .format(err)) if self.package_type.value() in ['all', 'os']: vulns = context.data.get('loaded_vulnerabilities') if vulns: # get nvd classes from context or select them once and be done _nvd_cls, _cpe_cls = context.data.get('nvd_cpe_cls', (None, None)) if not _nvd_cls or not _cpe_cls: _nvd_cls, _cpe_cls = select_nvd_classes() for pkg_vuln in vulns: parameter_data = OrderedDict() parameter_data[ 'severity'] = pkg_vuln.vulnerability.severity.upper() parameter_data[ 'vulnerability_id'] = pkg_vuln.vulnerability_id parameter_data['pkg_class'] = 'os' parameter_data['pkg_type'] = pkg_vuln.pkg_type # Filter by level first found_severity_idx = SEVERITY_ORDERING.index( pkg_vuln.vulnerability.severity.lower( )) if pkg_vuln.vulnerability.severity else 0 if comparison_fn(found_severity_idx, comparison_idx): # Check vendor_only flag specified by the user in policy if is_vendor_only: if pkg_vuln.fix_has_no_advisory(): # skip this vulnerability continue # Check if the vulnerability is to recent for this policy if timeallowed: if calendar.timegm( pkg_vuln.vulnerability.created_at. timetuple()) > timeallowed: continue parameter_data[ 'max_days_since_creation'] = pkg_vuln.vulnerability.created_at.date( ) if is_fix_available and fix_timeallowed is not None: fix = pkg_vuln.fixed_artifact() if fix.version and fix.version != 'None': if fix.fix_observed_at and calendar.timegm( fix.fix_observed_at.timetuple( )) > fix_timeallowed: continue else: parameter_data[ 'max_days_since_fix'] = fix.fix_observed_at.date( ) vuln_cvss_base_score = -1.0 vuln_cvss_exploitability_score = -1.0 vuln_cvss_impact_score = -1.0 for nvd_record in pkg_vuln.vulnerability.get_nvd_vulnerabilities( _nvd_cls=_nvd_cls, _cpe_cls=_cpe_cls): cvss_score = nvd_record.get_max_cvss_score_nvd() if cvss_score.get('base_score', -1.0) > vuln_cvss_base_score: vuln_cvss_base_score = cvss_score.get( 'base_score', -1.0) if cvss_score.get( 'exploitability_score', -1.0) > vuln_cvss_exploitability_score: vuln_cvss_exploitability_score = cvss_score.get( 'exploitability_score', -1.0) if cvss_score.get('impact_score', -1.0) > vuln_cvss_impact_score: vuln_cvss_impact_score = cvss_score.get( 'impact_score', -1.0) if cvss_v3_base_score is not None: if not cvss_v3_base_score_comparison_fn( vuln_cvss_base_score, cvss_v3_base_score): log.debug( "OS vulnerability {} cvss V3 base_score {} is not {} than policy cvss V3 base_score {}, skipping" .format( pkg_vuln.vulnerability_id, vuln_cvss_base_score, self.cvss_v3_base_score_comparison. value(), cvss_v3_base_score)) continue else: parameter_data[ 'cvss_v3_base_score'] = vuln_cvss_base_score if cvss_v3_exploitability_score is not None: if not cvss_v3_exploitability_score_comparison_fn( vuln_cvss_exploitability_score, cvss_v3_exploitability_score): log.debug( "OS vulnerability {} cvss V3 exploitability_score {} is not {} than policy cvss V3 exploitability_score {}, skipping" .format( pkg_vuln.vulnerability_id, vuln_cvss_exploitability_score, self. cvss_v3_exploitability_score_comparison .value(), cvss_v3_exploitability_score)) continue else: parameter_data[ 'cvss_v3_exploitability_score'] = vuln_cvss_exploitability_score if cvss_v3_impact_score is not None: if not cvss_v3_impact_score_comparison_fn( vuln_cvss_impact_score, cvss_v3_impact_score): log.debug( "OS vulnerability {} cvss V3 impact_score {} is not {} than policy cvss V3 impact_score {}, skipping" .format( pkg_vuln.vulnerability_id, vuln_cvss_impact_score, self.cvss_v3_impact_score_comparison. value(), cvss_v3_impact_score)) continue else: parameter_data[ 'cvss_v3_impact_score'] = vuln_cvss_impact_score # Check fix_available status if specified by user in policy if is_fix_available is not None: # Must to a fix_available check fix_available_in = pkg_vuln.fixed_in() if is_fix_available == (fix_available_in is not None): # explicit fix state check matches fix availability if is_fix_available: parameter_data[ 'fixed_version'] = fix_available_in parameter_data['link'] = pkg_vuln.vulnerability.link fix_msg = '' if parameter_data.get('fixed_version', None): fix_msg = "(fixed in: {})".format( parameter_data.get('fixed_version')) score_msg = '' score_tuples = [] for s in [ 'cvss_v3_base_score', 'cvss_v3_exploitability_score', 'cvss_v3_impact_score' ]: if parameter_data.get(s, None): score_tuples.append("{}={}".format( s, parameter_data.get(s))) if score_tuples: score_msg = "({})".format(' '.join(score_tuples)) time_msg = '' time_tuples = [] for s in [ 'max_days_since_creation', 'max_days_since_fix' ]: if parameter_data.get(s, None): time_tuples.append("{}={}".format( s, parameter_data.get(s))) if time_tuples: time_msg = "({})".format(' '.join(time_tuples)) # vendor vulnerability scores not currently available for os packages, this is a pass through vuln_vendor_cvss_base_score = -1.0 vuln_vendor_cvss_exploitability_score = -1.0 vuln_vendor_cvss_impact_score = -1.0 if vendor_cvss_v3_base_score is not None: if not vendor_cvss_v3_base_score_comparison_fn( vuln_vendor_cvss_base_score, vendor_cvss_v3_base_score): log.debug( "OS vulnerability {} vendor cvss V3 base score {} is not {} than policy vendor cvss V3 base score {}, skipping" .format( pkg_vuln.vulnerability_id, vuln_vendor_cvss_base_score, self. vendor_cvss_v3_base_score_comparison. value(), vendor_cvss_v3_base_score)) continue else: parameter_data[ 'vendor_cvss_v3_base_score'] = vuln_vendor_cvss_base_score if vendor_cvss_v3_exploitability_score is not None: if not vendor_cvss_v3_exploitability_score_comparison_fn( vuln_vendor_cvss_exploitability_score, vendor_cvss_v3_exploitability_score): log.debug( "OS vulnerability {} vendor cvss V3 exploitability sub score {} is not {} than policy vendor cvss V3 exploitability sub score {}, skipping" .format( pkg_vuln.vulnerability_id, vuln_vendor_cvss_exploitability_score, self. vendor_cvss_v3_exploitability_score_comparison .value(), vendor_cvss_v3_exploitability_score)) continue else: parameter_data[ 'vendor_cvss_v3_exploitability_score'] = vuln_vendor_cvss_exploitability_score if vendor_cvss_v3_impact_score is not None: if not vendor_cvss_v3_impact_score_comparison_fn( vuln_vendor_cvss_impact_score, vendor_cvss_v3_impact_score): log.debug( "OS vulnerability {} vendor cvss V3 impact sub score {} is not {} than policy vendor cvss V3 impact score {}, skipping" .format( pkg_vuln.vulnerability_id, vuln_vendor_cvss_impact_score, self. vendor_cvss_v3_impact_score_comparison. value(), vendor_cvss_v3_impact_score)) continue else: parameter_data[ 'vendor_cvss_v3_impact_score'] = vuln_vendor_cvss_impact_score vendor_score_msg = '' vendor_score_tuples = [] for s in [ 'vendor_cvss_v3_base_score', 'vendor_cvss_v3_exploitability_score', 'vendor_cvss_v3_impact_score' ]: if parameter_data.get(s, None): vendor_score_tuples.append("{}={}".format( s, parameter_data.get(s))) if vendor_score_tuples: vendor_score_msg = "({})".format( ' '.join(vendor_score_tuples)) # new detail message approach #pkgname = pkg_vuln.pkg_name #if pkg_vuln.pkg_version != 'None': # pkgname += "-{}".format(pkg_vuln.pkg_version) #msg = "Vulnerability found in package {} - matching parameters: ".format(pkgname) #for i in parameter_data: # msg += "{}={} ".format(i, parameter_data[i]) # original detail message approach pkgname = pkg_vuln.pkg_name msg = "{} Vulnerability found in {} package type ({}) - {} {}{}{}{}({} - {})".format( parameter_data['severity'].upper(), parameter_data['pkg_class'], parameter_data['pkg_type'], pkgname, fix_msg, score_msg, time_msg, vendor_score_msg, parameter_data['vulnerability_id'], parameter_data['link']) self._fire(instance_id=pkg_vuln.vulnerability_id + '+' + pkg_vuln.pkg_name, msg=msg)
def evaluate(self, image_obj, context): is_fix_available = self.fix_available.value() is_vendor_only = self.vendor_only.value(default_if_none=True) comparison_idx = SEVERITY_ORDERING.index( self.severity.value(default_if_none="unknown").lower()) comparison_fn = self.SEVERITY_COMPARISONS.get( self.severity_comparison.value(default_if_none=">")) cvss_v3_base_score = self.cvss_v3_base_score.value() cvss_v3_base_score_comparison_fn = self.SEVERITY_COMPARISONS.get( self.cvss_v3_base_score_comparison.value(default_if_none=">=")) cvss_v3_exploitability_score = self.cvss_v3_exploitability_score.value( ) cvss_v3_exploitability_score_comparison_fn = self.SEVERITY_COMPARISONS.get( self.cvss_v3_exploitability_score_comparison.value( default_if_none=">=")) cvss_v3_impact_score = self.cvss_v3_impact_score.value() cvss_v3_impact_score_comparison_fn = self.SEVERITY_COMPARISONS.get( self.cvss_v3_impact_score_comparison.value(default_if_none=">=")) now = time.time() timeallowed = None if self.max_days_since_creation.value() is not None: timeallowed = now - int( int(self.max_days_since_creation.value()) * 86400) fix_timeallowed = None if self.max_days_since_fix.value() is not None: fix_timeallowed = now - int( int(self.max_days_since_fix.value()) * 86400) if not comparison_fn: pass # raise KeyError(self.severity_comparison) vendor_cvss_v3_base_score = self.vendor_cvss_v3_base_score.value() vendor_cvss_v3_base_score_comparison_fn = self.SEVERITY_COMPARISONS.get( self.vendor_cvss_v3_base_score_comparison.value( default_if_none=">=")) vendor_cvss_v3_exploitability_score = ( self.vendor_cvss_v3_exploitability_score.value()) vendor_cvss_v3_exploitability_score_comparison_fn = ( self.SEVERITY_COMPARISONS.get( self.vendor_cvss_v3_exploitability_score_comparison.value( default_if_none=">="))) vendor_cvss_v3_impact_score = self.vendor_cvss_v3_impact_score.value() vendor_cvss_v3_impact_score_comparison_fn = self.SEVERITY_COMPARISONS.get( self.vendor_cvss_v3_impact_score_comparison.value( default_if_none=">=")) api_endpoint = ( None # for populating vulnerability links that point back to engine ) if self.package_type.value() in ["all", "non-os"]: cpevulns = context.data.get("loaded_cpe_vulnerabilities") if cpevulns: try: for sev in list(cpevulns.keys()): found_severity_idx = (SEVERITY_ORDERING.index( sev.lower()) if sev else 0) if comparison_fn(found_severity_idx, comparison_idx): for image_cpe, vulnerability_cpe in cpevulns[sev]: parameter_data = OrderedDict() parameter_data["severity"] = sev.upper() parameter_data[ "vulnerability_id"] = vulnerability_cpe.vulnerability_id parameter_data["pkg_class"] = "non-os" parameter_data["pkg_type"] = image_cpe.pkg_type # setting fixed_version here regardless of gate parameter, fix_available_in = vulnerability_cpe.get_fixed_in( ) if fix_available_in: parameter_data[ "fixed_version"] = ", ".join( fix_available_in) # Check if the vulnerability is too recent for this policy if timeallowed: if (calendar.timegm(vulnerability_cpe. created_at.timetuple()) > timeallowed): continue parameter_data[ "max_days_since_creation"] = vulnerability_cpe.created_at.date( ) if cvss_v3_base_score is not None: vuln_cvss_base_score = ( vulnerability_cpe.parent. get_max_base_score_nvd()) if not cvss_v3_base_score_comparison_fn( vuln_cvss_base_score, cvss_v3_base_score): logger.debug( "Non-OS vulnerability {} cvss V3 base score {} is not {} than policy cvss V3 base score {}, skipping" .format( vulnerability_cpe.parent.name, vuln_cvss_base_score, self. cvss_v3_base_score_comparison. value(), cvss_v3_base_score, )) continue else: parameter_data[ "cvss_v3_base_score"] = vuln_cvss_base_score if cvss_v3_exploitability_score is not None: vuln_cvss_exploitability_score = ( vulnerability_cpe.parent. get_max_exploitability_score_nvd()) if not cvss_v3_exploitability_score_comparison_fn( vuln_cvss_exploitability_score, cvss_v3_exploitability_score, ): logger.debug( "Non-OS vulnerability {} cvss V3 exploitability sub score {} is not {} than policy cvss V3 exploitability sub score {}, skipping" .format( vulnerability_cpe.parent.name, vuln_cvss_exploitability_score, self. cvss_v3_exploitability_score_comparison .value(), cvss_v3_exploitability_score, )) continue else: parameter_data[ "cvss_v3_exploitability_score"] = vuln_cvss_exploitability_score if cvss_v3_impact_score is not None: vuln_cvss_impact_score = ( vulnerability_cpe.parent. get_max_impact_score_nvd()) if not cvss_v3_impact_score_comparison_fn( vuln_cvss_impact_score, cvss_v3_impact_score): logger.debug( "Non-OS vulnerability {} cvss V3 impact sub score {} is not {} than policy cvss V3 impact score {}, skipping" .format( vulnerability_cpe.parent.name, vuln_cvss_impact_score, self. cvss_v3_impact_score_comparison .value(), cvss_v3_impact_score, )) continue else: parameter_data[ "cvss_v3_impact_score"] = vuln_cvss_impact_score trigger_fname = None if image_cpe.pkg_type in ["java", "gem"]: try: trigger_fname = image_cpe.pkg_path.split( "/")[-1] except: trigger_fname = None elif image_cpe.pkg_type in ["npm"]: try: trigger_fname = image_cpe.pkg_path.split( "/")[-2] except: trigger_fname = None if not trigger_fname: trigger_fname = "-".join( [image_cpe.name, image_cpe.version]) # Check fix_available status if specified by user in policy if is_fix_available is not None: # explicit fix state check matches fix availability if is_fix_available != ( fix_available_in is not None and len(fix_available_in) > 0): # if_fix_available is set but does not match is_fix_available check continue if is_fix_available and fix_timeallowed is not None: if fix_available_in: if (calendar.timegm( vulnerability_cpe. created_at.timetuple()) > fix_timeallowed): continue else: parameter_data[ "max_days_since_fix"] = vulnerability_cpe.created_at.date( ) if not vulnerability_cpe.parent.link: if not api_endpoint: api_endpoint = get_service_endpoint( "apiext").strip("/") parameter_data[ "link"] = "{}/query/vulnerabilities?id={}".format( api_endpoint, vulnerability_cpe.vulnerability_id) else: parameter_data[ "link"] = vulnerability_cpe.parent.link fix_msg = "" if parameter_data.get("fixed_version", None): fix_msg = "(fixed in: {})".format( parameter_data.get("fixed_version")) score_msg = "" score_tuples = [] for s in [ "cvss_v3_base_score", "cvss_v3_exploitability_score", "cvss_v3_impact_score", ]: if parameter_data.get(s, None): score_tuples.append("{}={}".format( s, parameter_data.get(s))) if score_tuples: score_msg = "({})".format( " ".join(score_tuples)) time_msg = "" time_tuples = [] for s in [ "max_days_since_creation", "max_days_since_fix", ]: if parameter_data.get(s, None): time_tuples.append("{}={}".format( s, parameter_data.get(s))) if time_tuples: time_msg = "({})".format( " ".join(time_tuples)) if vendor_cvss_v3_base_score is not None: vuln_vendor_cvss_base_score = ( vulnerability_cpe.parent. get_max_base_score_vendor()) if not vendor_cvss_v3_base_score_comparison_fn( vuln_vendor_cvss_base_score, vendor_cvss_v3_base_score, ): logger.debug( "Non-OS vulnerability {} vendor cvss V3 base score {} is not {} than policy vendor cvss V3 base score {}, skipping" .format( vulnerability_cpe.parent.name, vuln_vendor_cvss_base_score, self. vendor_cvss_v3_base_score_comparison .value(), vendor_cvss_v3_base_score, )) continue else: parameter_data[ "vendor_cvss_v3_base_score"] = vuln_vendor_cvss_base_score if vendor_cvss_v3_exploitability_score is not None: vuln_vendor_cvss_exploitability_score = ( vulnerability_cpe.parent. get_max_exploitability_score_vendor()) if not vendor_cvss_v3_exploitability_score_comparison_fn( vuln_vendor_cvss_exploitability_score, vendor_cvss_v3_exploitability_score, ): logger.debug( "Non-OS vulnerability {} vendor cvss V3 exploitability sub score {} is not {} than policy vendor cvss V3 exploitability sub score {}, skipping" .format( vulnerability_cpe.parent.name, vuln_vendor_cvss_exploitability_score, self. vendor_cvss_v3_exploitability_score_comparison .value(), vendor_cvss_v3_exploitability_score, )) continue else: parameter_data[ "vendor_cvss_v3_exploitability_score"] = vuln_vendor_cvss_exploitability_score if vendor_cvss_v3_impact_score is not None: vuln_vendor_cvss_impact_score = ( vulnerability_cpe.parent. get_max_impact_score_vendor()) if not vendor_cvss_v3_impact_score_comparison_fn( vuln_vendor_cvss_impact_score, vendor_cvss_v3_impact_score, ): logger.debug( "Non-OS vulnerability {} vendor cvss V3 impact sub score {} is not {} than policy vendor cvss V3 impact score {}, skipping" .format( vulnerability_cpe.parent.name, vuln_vendor_cvss_impact_score, self. vendor_cvss_v3_impact_score_comparison .value(), vendor_cvss_v3_impact_score, )) continue else: parameter_data[ "vendor_cvss_v3_impact_score"] = vuln_vendor_cvss_impact_score vendor_score_msg = "" vendor_score_tuples = [] for s in [ "vendor_cvss_v3_base_score", "vendor_cvss_v3_exploitability_score", "vendor_cvss_v3_impact_score", ]: if parameter_data.get(s, None): vendor_score_tuples.append( "{}={}".format( s, parameter_data.get(s))) if vendor_score_tuples: vendor_score_msg = "({})".format( " ".join(vendor_score_tuples)) # new detail message approach # pkgname = image_cpe.pkg_path # msg = "Vulnerability found in package {} - matching parameters: ".format(pkgname) # for i in parameter_data: # msg += "{}={} ".format(i, parameter_data[i]) pkgname = image_cpe.pkg_path msg = "{} Vulnerability found in {} package type ({}) - {} {}{}{}{}({} - {})".format( parameter_data["severity"].upper(), parameter_data["pkg_class"], parameter_data["pkg_type"], pkgname, fix_msg, score_msg, time_msg, vendor_score_msg, parameter_data["vulnerability_id"], parameter_data["link"], ) self._fire( instance_id=vulnerability_cpe. vulnerability_id + "+" + trigger_fname, msg=msg, ) except Exception as err: logger.warn( "problem during non-os vulnerability evaluation - exception: {}" .format(err)) # Process vulnerabilities that match using ImagePackageVulnerability objects, which can include all types as well vulns = context.data.get("loaded_vulnerabilities") if vulns: # get nvd classes from context or select them once and be done _nvd_cls, _cpe_cls = context.data.get("nvd_cpe_cls", (None, None)) if not _nvd_cls or not _cpe_cls: _nvd_cls, _cpe_cls = select_nvd_classes() pkg_type_value = self.package_type.value() for pkg_vuln in vulns: parameter_data = OrderedDict() parameter_data[ "severity"] = pkg_vuln.vulnerability.severity.upper() parameter_data["vulnerability_id"] = pkg_vuln.vulnerability_id parameter_data["pkg_type"] = pkg_vuln.pkg_type parameter_data["pkg_class"] = ("non-os" if pkg_vuln.pkg_type in nonos_package_types else "os") # setting fixed_version here regardless of gate parameter, fix_available_in = pkg_vuln.fixed_in() if fix_available_in: parameter_data["fixed_version"] = fix_available_in # Filter first by package class, if rule has a filter if (pkg_type_value != "all" and pkg_type_value != parameter_data["pkg_class"]): continue # Filter by level first found_severity_idx = (SEVERITY_ORDERING.index( pkg_vuln.vulnerability.severity.lower()) if pkg_vuln.vulnerability.severity else 0) if comparison_fn(found_severity_idx, comparison_idx): # Check vendor_only flag specified by the user in policy if is_vendor_only: if pkg_vuln.fix_has_no_advisory(): # skip this vulnerability continue # Check if the vulnerability is to recent for this policy if timeallowed: if (calendar.timegm( pkg_vuln.vulnerability.created_at.timetuple()) > timeallowed): continue parameter_data[ "max_days_since_creation"] = pkg_vuln.vulnerability.created_at.date( ) if is_fix_available and fix_timeallowed is not None: fix = pkg_vuln.fixed_artifact() if fix.version and fix.version != "None": if (fix.fix_observed_at and calendar.timegm( fix.fix_observed_at.timetuple()) > fix_timeallowed): continue else: parameter_data[ "max_days_since_fix"] = fix.fix_observed_at.date( ) vuln_cvss_base_score = -1.0 vuln_cvss_exploitability_score = -1.0 vuln_cvss_impact_score = -1.0 for nvd_record in pkg_vuln.vulnerability.get_nvd_vulnerabilities( _nvd_cls=_nvd_cls, _cpe_cls=_cpe_cls): cvss_score = nvd_record.get_max_cvss_score_nvd() if cvss_score.get("base_score", -1.0) > vuln_cvss_base_score: vuln_cvss_base_score = cvss_score.get( "base_score", -1.0) if (cvss_score.get("exploitability_score", -1.0) > vuln_cvss_exploitability_score): vuln_cvss_exploitability_score = cvss_score.get( "exploitability_score", -1.0) if (cvss_score.get("impact_score", -1.0) > vuln_cvss_impact_score): vuln_cvss_impact_score = cvss_score.get( "impact_score", -1.0) if cvss_v3_base_score is not None: if not cvss_v3_base_score_comparison_fn( vuln_cvss_base_score, cvss_v3_base_score): logger.debug( "OS vulnerability {} cvss V3 base_score {} is not {} than policy cvss V3 base_score {}, skipping" .format( pkg_vuln.vulnerability_id, vuln_cvss_base_score, self.cvss_v3_base_score_comparison.value(), cvss_v3_base_score, )) continue else: parameter_data[ "cvss_v3_base_score"] = vuln_cvss_base_score if cvss_v3_exploitability_score is not None: if not cvss_v3_exploitability_score_comparison_fn( vuln_cvss_exploitability_score, cvss_v3_exploitability_score): logger.debug( "OS vulnerability {} cvss V3 exploitability_score {} is not {} than policy cvss V3 exploitability_score {}, skipping" .format( pkg_vuln.vulnerability_id, vuln_cvss_exploitability_score, self. cvss_v3_exploitability_score_comparison. value(), cvss_v3_exploitability_score, )) continue else: parameter_data[ "cvss_v3_exploitability_score"] = vuln_cvss_exploitability_score if cvss_v3_impact_score is not None: if not cvss_v3_impact_score_comparison_fn( vuln_cvss_impact_score, cvss_v3_impact_score): logger.debug( "OS vulnerability {} cvss V3 impact_score {} is not {} than policy cvss V3 impact_score {}, skipping" .format( pkg_vuln.vulnerability_id, vuln_cvss_impact_score, self.cvss_v3_impact_score_comparison.value( ), cvss_v3_impact_score, )) continue else: parameter_data[ "cvss_v3_impact_score"] = vuln_cvss_impact_score # Check fix_available status if specified by user in policy if is_fix_available is not None: # explicit fix state check matches fix availability if is_fix_available != (fix_available_in is not None): # if_fix_available is set but does not match is_fix_available check continue parameter_data["link"] = pkg_vuln.vulnerability.link fix_msg = "" if parameter_data.get("fixed_version", None): fix_msg = "(fixed in: {})".format( parameter_data.get("fixed_version")) score_msg = "" score_tuples = [] for s in [ "cvss_v3_base_score", "cvss_v3_exploitability_score", "cvss_v3_impact_score", ]: if parameter_data.get(s, None): score_tuples.append("{}={}".format( s, parameter_data.get(s))) if score_tuples: score_msg = "({})".format(" ".join(score_tuples)) time_msg = "" time_tuples = [] for s in ["max_days_since_creation", "max_days_since_fix"]: if parameter_data.get(s, None): time_tuples.append("{}={}".format( s, parameter_data.get(s))) if time_tuples: time_msg = "({})".format(" ".join(time_tuples)) # vendor vulnerability scores not currently available for os packages, this is a pass through vuln_vendor_cvss_base_score = -1.0 vuln_vendor_cvss_exploitability_score = -1.0 vuln_vendor_cvss_impact_score = -1.0 if vendor_cvss_v3_base_score is not None: if not vendor_cvss_v3_base_score_comparison_fn( vuln_vendor_cvss_base_score, vendor_cvss_v3_base_score): logger.debug( "OS vulnerability {} vendor cvss V3 base score {} is not {} than policy vendor cvss V3 base score {}, skipping" .format( pkg_vuln.vulnerability_id, vuln_vendor_cvss_base_score, self.vendor_cvss_v3_base_score_comparison. value(), vendor_cvss_v3_base_score, )) continue else: parameter_data[ "vendor_cvss_v3_base_score"] = vuln_vendor_cvss_base_score if vendor_cvss_v3_exploitability_score is not None: if not vendor_cvss_v3_exploitability_score_comparison_fn( vuln_vendor_cvss_exploitability_score, vendor_cvss_v3_exploitability_score, ): logger.debug( "OS vulnerability {} vendor cvss V3 exploitability sub score {} is not {} than policy vendor cvss V3 exploitability sub score {}, skipping" .format( pkg_vuln.vulnerability_id, vuln_vendor_cvss_exploitability_score, self. vendor_cvss_v3_exploitability_score_comparison .value(), vendor_cvss_v3_exploitability_score, )) continue else: parameter_data[ "vendor_cvss_v3_exploitability_score"] = vuln_vendor_cvss_exploitability_score if vendor_cvss_v3_impact_score is not None: if not vendor_cvss_v3_impact_score_comparison_fn( vuln_vendor_cvss_impact_score, vendor_cvss_v3_impact_score): logger.debug( "OS vulnerability {} vendor cvss V3 impact sub score {} is not {} than policy vendor cvss V3 impact score {}, skipping" .format( pkg_vuln.vulnerability_id, vuln_vendor_cvss_impact_score, self.vendor_cvss_v3_impact_score_comparison .value(), vendor_cvss_v3_impact_score, )) continue else: parameter_data[ "vendor_cvss_v3_impact_score"] = vuln_vendor_cvss_impact_score vendor_score_msg = "" vendor_score_tuples = [] for s in [ "vendor_cvss_v3_base_score", "vendor_cvss_v3_exploitability_score", "vendor_cvss_v3_impact_score", ]: if parameter_data.get(s, None): vendor_score_tuples.append("{}={}".format( s, parameter_data.get(s))) if vendor_score_tuples: vendor_score_msg = "({})".format( " ".join(vendor_score_tuples)) # new detail message approach # pkgname = pkg_vuln.pkg_name # if pkg_vuln.pkg_version != 'None': # pkgname += "-{}".format(pkg_vuln.pkg_version) # msg = "Vulnerability found in package {} - matching parameters: ".format(pkgname) # for i in parameter_data: # msg += "{}={} ".format(i, parameter_data[i]) # original detail message approach pkgname = pkg_vuln.pkg_name msg = "{} Vulnerability found in {} package type ({}) - {} {}{}{}{}({} - {})".format( parameter_data["severity"].upper(), parameter_data["pkg_class"], parameter_data["pkg_type"], pkgname, fix_msg, score_msg, time_msg, vendor_score_msg, parameter_data["vulnerability_id"], parameter_data["link"], ) self._fire( instance_id=pkg_vuln.vulnerability_id + "+" + pkg_vuln.pkg_name, msg=msg, )