Message ID | 20230921090316.10932-1-shin.matsunaga@fujitsu.com |
---|---|
State | New |
Headers | show |
Series | cve-check: Classify patched CVEs into 3 statuses | expand |
We have recently introduced CVE_CHECK_STATUSMAP which should be used to declare more detailed status information instead of introducing additional statuses. In this case, "out of range" should be subtype of patched and "undecidable" subtype of unpatched I think. Peter -----Original Message----- From: openembedded-core@lists.openembedded.org <openembedded-core@lists.openembedded.org> On Behalf Of Matsunaga-Shinji via lists.openembedded.org Sent: Thursday, September 21, 2023 11:03 To: richard.purdie@linuxfoundation.org Cc: openembedded-core@lists.openembedded.org; shin.matsunaga@fujitsu.com Subject: [OE-core] [PATCH] cve-check: Classify patched CVEs into 3 statuses > 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. "Out of range" - means that the package version (PV) is not subject to the vulnerability > 3. "Undecidable" - means that versions cannot be compared to determine if they are affected by the vulnerability > > Signed-off-by: Shinji Matsunaga <shin.matsunaga@fujitsu.com>
Sorry for the late reply. In addition to the changes to meta/classes/cve-check.bbclass, Does it mean that the following processing needs to be added to meta/conf/cve-check-map.conf? CVE_CHECK_STATUSMAP[out-of-range] = "Patched" CVE_CHECK_STATUSMAP[undecidable] = "Unpatched" Shinji -----Original Message----- From: Marko, Peter <Peter.Marko@siemens.com> Sent: Thursday, September 21, 2023 6:46 PM To: Matsunaga, Shinji/松永 慎司 <shin.matsunaga@fujitsu.com>; richard.purdie@linuxfoundation.org Cc: openembedded-core@lists.openembedded.org Subject: RE: [OE-core] [PATCH] cve-check: Classify patched CVEs into 3 statuses We have recently introduced CVE_CHECK_STATUSMAP which should be used to declare more detailed status information instead of introducing additional statuses. In this case, "out of range" should be subtype of patched and "undecidable" subtype of unpatched I think. Peter -----Original Message----- From: openembedded-core@lists.openembedded.org <openembedded-core@lists.openembedded.org> On Behalf Of Matsunaga-Shinji via lists.openembedded.org Sent: Thursday, September 21, 2023 11:03 To: richard.purdie@linuxfoundation.org Cc: openembedded-core@lists.openembedded.org; shin.matsunaga@fujitsu.com Subject: [OE-core] [PATCH] cve-check: Classify patched CVEs into 3 statuses > 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. "Out of range" - means that the package version (PV) is not subject > to the vulnerability 3. "Undecidable" - means that versions cannot be > compared to determine if they are affected by the vulnerability > > Signed-off-by: Shinji Matsunaga <shin.matsunaga@fujitsu.com>
On Thu, 21 Sept 2023, 11:03 Matsunaga-Shinji, <shin.matsunaga@fujitsu.com> 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. "Out of range" - means that the package version (PV) is not subject to > the vulnerability > 3. "Undecidable" - means that versions cannot be compared to determine if > they are affected by the vulnerability Hello, Thank you for your patch. I'm wondering what you use case is. What do you do with that data? Currently in YP we aim to do as much as automatic classification as we can. We only adjust the classification manually when it is clearly wrong. Now, in this piece of code I don't see setting up 'out-of-range', while it is possible to separate the not affected case and the case when we apply a patch. I do not understand the 'undecideable' classification. Could you give an exemple of a situation when it makes sense to use it? On the naming side, I'd prefer 'Not Affected' for out-of-range, because that term is often used in error conditions. In this case there is no error at all. Kind regards, Marta >
Yes, that's how we designed this feature. Peter -----Original Message----- From: Shinji Matsunaga (Fujitsu) <shin.matsunaga@fujitsu.com> Sent: Wednesday, October 4, 2023 4:19 To: Marko, Peter (ADV D EU SK BFS1) <Peter.Marko@siemens.com>; richard.purdie@linuxfoundation.org Cc: openembedded-core@lists.openembedded.org Subject: RE: [OE-core] [PATCH] cve-check: Classify patched CVEs into 3 statuses > Sorry for the late reply. > > In addition to the changes to meta/classes/cve-check.bbclass, Does it mean that the following processing needs to be added to meta/conf/cve-check-map.conf? > CVE_CHECK_STATUSMAP[out-of-range] = "Patched" > CVE_CHECK_STATUSMAP[undecidable] = "Unpatched" > > Shinji > > -----Original Message----- > From: Marko, Peter <Peter.Marko@siemens.com> > Sent: Thursday, September 21, 2023 6:46 PM > To: Matsunaga, Shinji/松永 慎司 <shin.matsunaga@fujitsu.com>; richard.purdie@linuxfoundation.org > Cc: openembedded-core@lists.openembedded.org > Subject: RE: [OE-core] [PATCH] cve-check: Classify patched CVEs into 3 statuses > > We have recently introduced CVE_CHECK_STATUSMAP which should be used to declare more detailed status information instead of introducing additional statuses. > In this case, "out of range" should be subtype of patched and "undecidable" subtype of unpatched I think. > > Peter > > -----Original Message----- > From: openembedded-core@lists.openembedded.org <openembedded-core@lists.openembedded.org> On Behalf Of Matsunaga-Shinji via lists.openembedded.org > Sent: Thursday, September 21, 2023 11:03 > To: richard.purdie@linuxfoundation.org > Cc: openembedded-core@lists.openembedded.org; shin.matsunaga@fujitsu.com > Subject: [OE-core] [PATCH] cve-check: Classify patched CVEs into 3 statuses > > > 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. "Out of range" - means that the package version (PV) is not subject > > to the vulnerability 3. "Undecidable" - means that versions cannot be > > compared to determine if they are affected by the vulnerability > > > > Signed-off-by: Shinji Matsunaga <shin.matsunaga@fujitsu.com>
Sorry for the late reply.
We want to use "Patched" to make it easy to find the package where the patch file exists
and use "Out of range" to make it easy to find the package where not affected by the vulnerability.
For that, we consider we need to classify vulnerabilities to "Undecidable" that cannot determine if they are affected by the vulnerability, too.
As described above, "Out of range" means that the not affected case.
As you pointed out, We will change the name to "Not affected."
"Undecidable" is the status when "Failed to compare ..." is output.
(see cve-check.bbclass:check_cves())
Here is an example of "Undecidable".
PACKAGE NAME: synergy
PACKAGE VERSION: git
CVE: CVE-2020-15117
The log is as follows:
"WARNING: synergy: Failed to compare git < 1.12.0 for CVE-2020-15117"
Shinji
From: Marta Rybczynska <rybczynska@gmail.com>
Sent: Wednesday, October 4, 2023 12:59 PM
To: Matsunaga, Shinji/松永 慎司 <shin.matsunaga@fujitsu.com>
Cc: Richard Purdie <richard.purdie@linuxfoundation.org>; OE-core <openembedded-core@lists.openembedded.org>
Subject: Re: [OE-core] [PATCH] cve-check: Classify patched CVEs into 3 statuses
On Thu, 21 Sept 2023, 11:03 Matsunaga-Shinji, <shin.matsunaga@fujitsu.com<mailto:shin.matsunaga@fujitsu.com>> 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. "Out of range" - means that the package version (PV) is not subject to the vulnerability
3. "Undecidable" - means that versions cannot be compared to determine if they are affected by the vulnerability
Hello,
Thank you for your patch. I'm wondering what you use case is. What do you do with that data? Currently in YP we aim to do as much as automatic classification as we can. We only adjust the classification manually when it is clearly wrong.
Now, in this piece of code I don't see setting up 'out-of-range', while it is possible to separate the not affected case and the case when we apply a patch. I do not understand the 'undecideable' classification. Could you give an exemple of a situation when it makes sense to use it?
On the naming side, I'd prefer 'Not Affected' for out-of-range, because that term is often used in error conditions. In this case there is no error at all.
Kind regards,
Marta
diff --git a/meta/classes/cve-check.bbclass b/meta/classes/cve-check.bbclass index 55ae298024..a2456902ce 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, out_of_range, undecidable, status = check_cves(d, patched_cves) + if patched or unpatched or out_of_range or undecidable or (d.getVar("CVE_CHECK_COVERAGE") == "1" and status): + cve_data = get_cve_info(d, patched + unpatched + ignored + out_of_range + undecidable) + cve_write_data(d, patched, unpatched, ignored, out_of_range, 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_out_of_range = [] + 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_out_of_range.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_out_of_range, cves_undecidable, cves_status) def get_cve_info(d, cves): """ @@ -446,7 +454,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, out_of_range, undecidable, cve_data): """ Write CVE information in WORKDIR; and to CVE_CHECK_DIR, and CVE manifest if enabled. @@ -470,7 +478,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+out_of_range+undecidable: return nvd_link = "https://nvd.nist.gov/vuln/detail/" @@ -481,6 +489,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_out_of_range = cve in out_of_range + is_undecidable = cve in undecidable status = "Unpatched" if (is_patched or is_ignored) and not report_all: @@ -489,6 +499,10 @@ def cve_write_data_text(d, patched, unpatched, ignored, cve_data): status = "Ignored" elif is_patched: status = "Patched" + elif is_out_of_range: + status = "Out of range" + elif is_undecidable: + status = "Undecidable" else: # default value of status is Unpatched unpatched_cves.append(cve) @@ -559,7 +573,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, out_of_range, undecidable, cve_data, cve_status): """ Prepare CVE data for the JSON format, then write it. """ @@ -604,6 +618,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_out_of_range = cve in out_of_range + is_undecidable = cve in undecidable + status = "Unpatched" if (is_patched or is_ignored) and not report_all: continue @@ -611,6 +628,10 @@ def cve_write_data_json(d, patched, unpatched, ignored, cve_data, cve_status): status = "Ignored" elif is_patched: status = "Patched" + elif is_out_of_range: + status = "Out of range" + elif is_undecidable: + status = "Undecidable" else: # default value of status is Unpatched unpatched_cves.append(cve) @@ -642,12 +663,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, out_of_range, 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, out_of_range, 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, out_of_range, undecidable, cve_data, status)
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. "Out of range" - means that the package version (PV) is not subject to the vulnerability 3. "Undecidable" - means that versions cannot be compared to determine if they are affected by the vulnerability Signed-off-by: Shinji Matsunaga <shin.matsunaga@fujitsu.com> --- meta/classes/cve-check.bbclass | 55 +++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 17 deletions(-)