Hi Andrej, This is more complex. "Not affected" is also an issue that isn't present in the code - like when we have a version that has never had the vulnerability. Those are also currently 'Patched' in cve-check.
This work is in sync with what VEX is doing, is it the use-case Matsanaga-Shinji? Regards, Marta On Wed, Oct 25, 2023 at 8:44 AM Andrej Valek <[email protected]> wrote: > > Hi all, > > Do we really need a new "not_affected" state? I guess the ignore state > is exactly designed for those purposes. > > Regards, > Andrej > > On 25.10.2023 07:13, Matsunaga-Shinji wrote: > > CVEs that are currently considered "Patched" are classified into the > > following 3 statuses: > > 1. "Patched" - means that a patch file that fixed the vulnerability > > has been applied > > 2. "Not affected" - means that the package version (PV) is not affected by > > the vulnerability > > 3. "Undecidable" - means that versions cannot be compared to determine if > > they are affected by the vulnerability > > > > Signed-off-by: Shinji Matsunaga <[email protected]> > > Signed-off-by: Shunsuke Tokumoto <[email protected]> > > --- > > > > Changes for v2: > > - Fix the status "Out of range" to "Not affected" > > > > meta/classes/cve-check.bbclass | 55 +++++++++++++++++++++++----------- > > 1 file changed, 38 insertions(+), 17 deletions(-) > > > > diff --git a/meta/classes/cve-check.bbclass b/meta/classes/cve-check.bbclass > > index b55f4299da..502db324df 100644 > > --- a/meta/classes/cve-check.bbclass > > +++ b/meta/classes/cve-check.bbclass > > @@ -185,10 +185,10 @@ python do_cve_check () { > > patched_cves = get_patched_cves(d) > > except FileNotFoundError: > > bb.fatal("Failure in searching patches") > > - ignored, patched, unpatched, status = check_cves(d, > > patched_cves) > > - if patched or unpatched or (d.getVar("CVE_CHECK_COVERAGE") == > > "1" and status): > > - cve_data = get_cve_info(d, patched + unpatched + ignored) > > - cve_write_data(d, patched, unpatched, ignored, cve_data, > > status) > > + ignored, patched, unpatched, not_affected, undecidable, status > > = check_cves(d, patched_cves) > > + if patched or unpatched or not_affected or undecidable or > > (d.getVar("CVE_CHECK_COVERAGE") == "1" and status): > > + cve_data = get_cve_info(d, patched + unpatched + ignored + > > not_affected + undecidable) > > + cve_write_data(d, patched, unpatched, ignored, > > not_affected, undecidable, cve_data, status) > > else: > > bb.note("No CVE database found, skipping CVE check") > > > > @@ -308,13 +308,13 @@ def check_cves(d, patched_cves): > > products = d.getVar("CVE_PRODUCT").split() > > # If this has been unset then we're not scanning for CVEs here (for > > example, image recipes) > > if not products: > > - return ([], [], [], []) > > + return ([], [], [], [], [], []) > > pv = d.getVar("CVE_VERSION").split("+git")[0] > > > > # If the recipe has been skipped/ignored we return empty lists > > if pn in d.getVar("CVE_CHECK_SKIP_RECIPE").split(): > > bb.note("Recipe has been skipped by cve-check") > > - return ([], [], [], []) > > + return ([], [], [], [], [], []) > > > > # Convert CVE_STATUS into ignored CVEs and check validity > > cve_ignore = [] > > @@ -328,6 +328,8 @@ def check_cves(d, patched_cves): > > conn = sqlite3.connect(db_file, uri=True) > > > > # For each of the known product names (e.g. curl has CPEs using curl > > and libcurl)... > > + cves_not_affected = [] > > + cves_undecidable = [] > > for product in products: > > cves_in_product = False > > if ":" in product: > > @@ -355,6 +357,7 @@ def check_cves(d, patched_cves): > > > > vulnerable = False > > ignored = False > > + undecidable = False > > > > product_cursor = conn.execute("SELECT * FROM PRODUCTS WHERE > > ID IS ? AND PRODUCT IS ? AND VENDOR LIKE ?", (cve, product, vendor)) > > for row in product_cursor: > > @@ -376,7 +379,7 @@ def check_cves(d, patched_cves): > > except: > > bb.warn("%s: Failed to compare %s %s %s for > > %s" % > > (product, pv, operator_start, > > version_start, cve)) > > - vulnerable_start = False > > + undecidable = True > > else: > > vulnerable_start = False > > > > @@ -387,10 +390,15 @@ def check_cves(d, patched_cves): > > except: > > bb.warn("%s: Failed to compare %s %s %s for > > %s" % > > (product, pv, operator_end, > > version_end, cve)) > > - vulnerable_end = False > > + undecidable = True > > else: > > vulnerable_end = False > > > > + if undecidable: > > + bb.note("%s-%s is undecidable to %s" % (pn, > > real_pv, cve)) > > + cves_undecidable.append(cve) > > + break > > + > > if operator_start and operator_end: > > vulnerable = vulnerable_start and vulnerable_end > > else: > > @@ -406,9 +414,9 @@ def check_cves(d, patched_cves): > > break > > product_cursor.close() > > > > - if not vulnerable: > > + if not undecidable and not vulnerable: > > bb.note("%s-%s is not vulnerable to %s" % (pn, real_pv, > > cve)) > > - patched_cves.add(cve) > > + cves_not_affected.append(cve) > > cve_cursor.close() > > > > if not cves_in_product: > > @@ -420,7 +428,7 @@ def check_cves(d, patched_cves): > > if not cves_in_recipe: > > bb.note("No CVE records for products in recipe %s" % (pn)) > > > > - return (list(cves_ignored), list(patched_cves), cves_unpatched, > > cves_status) > > + return (list(cves_ignored), list(patched_cves), cves_unpatched, > > cves_not_affected, cves_undecidable, cves_status) > > > > def get_cve_info(d, cves): > > """ > > @@ -447,7 +455,7 @@ def get_cve_info(d, cves): > > conn.close() > > return cve_data > > > > -def cve_write_data_text(d, patched, unpatched, ignored, cve_data): > > +def cve_write_data_text(d, patched, unpatched, ignored, not_affected, > > undecidable, cve_data): > > """ > > Write CVE information in WORKDIR; and to CVE_CHECK_DIR, and > > CVE manifest if enabled. > > @@ -471,7 +479,7 @@ def cve_write_data_text(d, patched, unpatched, ignored, > > cve_data): > > return > > > > # Early exit, the text format does not report packages without CVEs > > - if not patched+unpatched+ignored: > > + if not patched+unpatched+ignored+not_affected+undecidable: > > return > > > > nvd_link = "https://nvd.nist.gov/vuln/detail/" > > @@ -482,6 +490,8 @@ def cve_write_data_text(d, patched, unpatched, ignored, > > cve_data): > > for cve in sorted(cve_data): > > is_patched = cve in patched > > is_ignored = cve in ignored > > + is_not_affected = cve in not_affected > > + is_undecidable = cve in undecidable > > > > status = "Unpatched" > > if (is_patched or is_ignored) and not report_all: > > @@ -490,6 +500,10 @@ def cve_write_data_text(d, patched, unpatched, > > ignored, cve_data): > > status = "Ignored" > > elif is_patched: > > status = "Patched" > > + elif is_not_affected: > > + status = "Not affected" > > + elif is_undecidable: > > + status = "Undecidable" > > else: > > # default value of status is Unpatched > > unpatched_cves.append(cve) > > @@ -561,7 +575,7 @@ def cve_check_write_json_output(d, output, direct_file, > > deploy_file, manifest_fi > > with open(index_path, "a+") as f: > > f.write("%s\n" % fragment_path) > > > > -def cve_write_data_json(d, patched, unpatched, ignored, cve_data, > > cve_status): > > +def cve_write_data_json(d, patched, unpatched, ignored, not_affected, > > undecidable, cve_data, cve_status): > > """ > > Prepare CVE data for the JSON format, then write it. > > """ > > @@ -606,6 +620,9 @@ def cve_write_data_json(d, patched, unpatched, ignored, > > cve_data, cve_status): > > for cve in sorted(cve_data): > > is_patched = cve in patched > > is_ignored = cve in ignored > > + is_not_affected = cve in not_affected > > + is_undecidable = cve in undecidable > > + > > status = "Unpatched" > > if (is_patched or is_ignored) and not report_all: > > continue > > @@ -613,6 +630,10 @@ def cve_write_data_json(d, patched, unpatched, > > ignored, cve_data, cve_status): > > status = "Ignored" > > elif is_patched: > > status = "Patched" > > + elif is_not_affected: > > + status = "Not affected" > > + elif is_undecidable: > > + status = "Undecidable" > > else: > > # default value of status is Unpatched > > unpatched_cves.append(cve) > > @@ -645,12 +666,12 @@ def cve_write_data_json(d, patched, unpatched, > > ignored, cve_data, cve_status): > > > > cve_check_write_json_output(d, output, direct_file, deploy_file, > > manifest_file) > > > > -def cve_write_data(d, patched, unpatched, ignored, cve_data, status): > > +def cve_write_data(d, patched, unpatched, ignored, not_affected, > > undecidable, cve_data, status): > > """ > > Write CVE data in each enabled format. > > """ > > > > if d.getVar("CVE_CHECK_FORMAT_TEXT") == "1": > > - cve_write_data_text(d, patched, unpatched, ignored, cve_data) > > + cve_write_data_text(d, patched, unpatched, ignored, not_affected, > > undecidable, cve_data) > > if d.getVar("CVE_CHECK_FORMAT_JSON") == "1": > > - cve_write_data_json(d, patched, unpatched, ignored, cve_data, > > status) > > + cve_write_data_json(d, patched, unpatched, ignored, not_affected, > > undecidable, cve_data, status) > > > > > > >
-=-=-=-=-=-=-=-=-=-=-=- Links: You receive all messages sent to this group. View/Reply Online (#189672): https://lists.openembedded.org/g/openembedded-core/message/189672 Mute This Topic: https://lists.openembedded.org/mt/102172913/21656 Group Owner: [email protected] Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [[email protected]] -=-=-=-=-=-=-=-=-=-=-=-
