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 ""
Esempio n. 2
0
 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>"
Esempio n. 3
0
 def get_url(self, servicename, base_route=None):
     endpt = get_service_endpoint(servicename)
     if base_route:
         return '/'.join([endpt, base_route])
     else:
         return endpt
Esempio n. 4
0
    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,
                    )