From patchwork Wed Mar 18 05:39:03 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Het Patel -X (hetpat - E INFOCHIPS PRIVATE LIMITED at Cisco)" X-Patchwork-Id: 83698 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 76A8DFCD0B8 for ; Wed, 18 Mar 2026 05:39:17 +0000 (UTC) Received: from rcdn-iport-5.cisco.com (rcdn-iport-5.cisco.com [173.37.86.76]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.7590.1773812349295877277 for ; Tue, 17 Mar 2026 22:39:09 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="dkim: message contains an insecure body length tag" header.i=@cisco.com header.s=iport01 header.b=Iv3onUam; spf=pass (domain: cisco.com, ip: 173.37.86.76, mailfrom: hetpat@cisco.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=5947; q=dns/txt; s=iport01; t=1773812349; x=1775021949; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=RPz35DxSaIaZcoE9qJ2U275qxVI3j6VH5ytLgamlQ6U=; b=Iv3onUamD39M7P7m5iLWi2PCvuh/Q2BBnsa900wUn0JnFr0fnrgcEGtq Uok6ZYwkt1EIKG3CHToZIy8VQAzm4Bjd/JKl0M3PaOlRuS5Au0NhkzGcF u4ppd8xs9ywiatbaZVFCJkAt79ikVM3gpuz/CsKbGKX8PCOJ0hd+4MfmG z4hyWBYWv7GZ2WHL5wDE/kaMuYIpcrNAG3lt2v+ZbC0iohlAuXp9E4Qpm kkk+ClEgwLkXtJCDg6+vQ/lVsD57Qdt6wRJdNVqGIs8134lUFelszIVBS NEGn6+hHTds2fHn4G4OaVYsorZV9hPFxbVTyvsOrNQVocnfJEsUvi4enb g==; X-CSE-ConnectionGUID: 9oy/KgwoRJyCp/u2vJq7bQ== X-CSE-MsgGUID: JN+5zb2BSg+0Y5MLs4dNKg== X-IPAS-Result: A0D0BQA1Obpp/5IQJK1aglmCSA+BUEJJlksDi2SSNoF/DwEBAQ9RBAEBhQcCjSICJjQJDgECBAEBAQEDAgMBAQEBAQEBAQEBAQsBAQUBAQECAQcFgQ4ThlyGWwIBAzIBRhAgMSALKxmDAoI7AzYCAbMOgiyBAd1DDYJSAQsUAYE4hTyCeYUgWhqEeicbG4FyhH2CH4hoBIIigQ6Ef4ZHhzZIgR4DWSwBVRMNCgsHBYFmAzUSKhVuMh2BIz4XgQsbBwWEAA+IbXRtgROEDAMLGA1IESw3FBsEPm4HjU87gUFsBwGBDQFCCTArIJRQPZF4oB1xCiiDdJtchXwaM6prLphYkhKSR4RogWg8gVlwFYMiUhkPiACGX8lDIzU9AgcCBw0DC5NlAQE IronPort-Data: A9a23:mlJecaOlzWegzeHvrR3xlsFynXyQoLVcMsEvi/4bfWQNrUog3jZVy 2AbCjiOOPqNZmL1f4glbNywoB5V7JWHx9dqTnM5pCpnJ55oRWUpJjg4wmPYZX76whjrFRo/h ykmQoCeaphyFTmE+kvF3oHJ9RFUzbuPSqf3FNnKMyVwQR4MYCo6gHqPocZh6mJTqYb/WVjlV e/a+ZWFZgf+gmEsaAr41orawP9RlKWq0N8nlgRWicBj5Df2i3QTBZQDEqC9R1OQapVUBOOzW 9HYx7i/+G7Dlz91Yj9yuu+mGqGiaue60Tmm0hK6aYD76vRxjnBaPpIACRYpQRw/ZwNlMDxG4 I4lWZSYEW/FN0BX8QgXe0Ew/ypWZcWq9FJbSJSymZT78qHIT5fj66RpHQYVMpIfwMRmKnkJ6 KYGCilSZCnW0opawJrjIgVtrs0nKM+uOMYUvWttiGmIS/0nWpvEBa7N4Le03h9p2ZsIRqiYP pRfMGYxBPjDS0Un1lM/CJ8ihO60rnL+aDZf7lmSoMLb5kCPklcojeKxbIK9ltqiZ+MWw1SS/ Ej98CehM0w/EMfDxRym/Sf57gPItWahMG4IL5W/7vNsjViZy2AfBRFTXlyhrNG9i1WiQJRYM 0ES9y8koKQ++UDtScPyNyBUu1aNuhoaHt4VGOog5UTVm+zf4h2SAS4PSTsphMEaifLajAcCj jeh9+4FzxQ12FFJYRpxLoupkA4= IronPort-HdrOrdr: A9a23:K6w3DKzqgpZilDla7eSzKrPwK71zdoMgy1knxilNoNJuHfBw8P re+8jzuiWUtN98YhwdcJW7Scu9qBDnhPpICPcqXYtKNTOO0ADDEGgh1/qG/9SKIUPDH4BmuZ uIC5IOa+EZyTNB/L/HCM7SKadH/OW6 X-Talos-CUID: 9a23:AaZkYWjuab6zMvquwsoMuutevDJuI3rMi1TfPEiCK3dCUPqIE0Gy4fxuqp87 X-Talos-MUID: 9a23:XG8JCQ3FrXtHfRhEt3hGHB0ErzUjwYLtVVIHy789tIrcBHFVHyzBgBKUTdpy X-IronPort-Anti-Spam-Filtered: true X-IronPort-AV: E=Sophos;i="6.23,126,1770595200"; d="scan'208";a="463152440" Received: from alln-l-core-09.cisco.com ([173.36.16.146]) by rcdn-iport-5.cisco.com with ESMTP/TLS/TLS_AES_256_GCM_SHA384; 18 Mar 2026 05:39:08 +0000 Received: from sjc-ads-8556.cisco.com (sjc-ads-8556.cisco.com [171.68.222.95]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by alln-l-core-09.cisco.com (Postfix) with ESMTPS id 44E9C18000146; Wed, 18 Mar 2026 05:39:08 +0000 (GMT) Received: by sjc-ads-8556.cisco.com (Postfix, from userid 1847788) id E20A3CE2A78; Tue, 17 Mar 2026 22:39:07 -0700 (PDT) From: "Het Patel -X (hetpat - E INFOCHIPS PRIVATE LIMITED at Cisco)" To: openembedded-core@lists.openembedded.org Cc: xe-linux-external@cisco.com, vchavda@cisco.com Subject: [OE-core] [scarthgap] [PATCH v1 1/4] cve-check: encode affected product/vendor in CVE_STATUS Date: Tue, 17 Mar 2026 22:39:03 -0700 Message-Id: <20260318053906.26606-2-hetpat@cisco.com> X-Mailer: git-send-email 2.35.6 In-Reply-To: <20260318053906.26606-1-hetpat@cisco.com> References: <20260318053906.26606-1-hetpat@cisco.com> MIME-Version: 1.0 X-Outbound-SMTP-Client: 171.68.222.95, sjc-ads-8556.cisco.com X-Outbound-Node: alln-l-core-09.cisco.com List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 18 Mar 2026 05:39:17 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/233359 From: Marta Rybczynska CVE_STATUS contains assesment of a given CVE, but until now it didn't have include the affected vendor/product. In the case of a global system include, that CVE_STATUS was visible in all recipes. This patch allows encoding of affected product/vendor to each CVE_STATUS assessment, also for groups. We can then filter them later and use only CVEs that correspond to the recipe. This is going to be used in meta/conf/distro/include/cve-extra-exclusions.inc and similar places. Backport Changes: - Discarded the changes to meta/lib/oe/spdx30_tasks.py, as the commit history for this file diverges from the base commit itself (9c9b9545049a in the scarthgap branch). - Additionally, the changes do not introduce any major features and are primarily focused on code restructuring. Signed-off-by: Marta Rybczynska Signed-off-by: Richard Purdie (cherry picked from commit abca80a716e92fc18d3085aba1a15f4bac72379c) Signed-off-by: Het Patel --- meta/classes/cve-check.bbclass | 24 ++++++++++----------- meta/lib/oe/cve_check.py | 39 ++++++++++++++++++++++++++-------- 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/meta/classes/cve-check.bbclass b/meta/classes/cve-check.bbclass index 3f4704fb4e..de5ddf6f04 100644 --- a/meta/classes/cve-check.bbclass +++ b/meta/classes/cve-check.bbclass @@ -316,8 +316,8 @@ def check_cves(d, patched_cves): # Convert CVE_STATUS into ignored CVEs and check validity cve_ignore = [] for cve in (d.getVarFlags("CVE_STATUS") or {}): - decoded_status, _, _ = decode_cve_status(d, cve) - if decoded_status == "Ignored": + decoded_status = decode_cve_status(d, cve) + if 'mapping' in decoded_status and decoded_status['mapping'] == "Ignored": cve_ignore.append(cve) import sqlite3 @@ -500,11 +500,11 @@ def cve_write_data_text(d, patched, unpatched, ignored, cve_data): write_string += "PACKAGE VERSION: %s%s\n" % (d.getVar("EXTENDPE"), d.getVar("PV")) write_string += "CVE: %s\n" % cve write_string += "CVE STATUS: %s\n" % status - _, detail, description = decode_cve_status(d, cve) - if detail: - write_string += "CVE DETAIL: %s\n" % detail - if description: - write_string += "CVE DESCRIPTION: %s\n" % description + status_details = decode_cve_status(d, cve) + if 'detail' in status_details: + write_string += "CVE DETAIL: %s\n" % status_details['detail'] + if 'description' in status_details: + write_string += "CVE DESCRIPTION: %s\n" % status_details['description'] write_string += "CVE SUMMARY: %s\n" % cve_data[cve]["summary"] write_string += "CVSS v2 BASE SCORE: %s\n" % cve_data[cve]["scorev2"] write_string += "CVSS v3 BASE SCORE: %s\n" % cve_data[cve]["scorev3"] @@ -632,11 +632,11 @@ def cve_write_data_json(d, patched, unpatched, ignored, cve_data, cve_status): "status" : status, "link": issue_link } - _, detail, description = decode_cve_status(d, cve) - if detail: - cve_item["detail"] = detail - if description: - cve_item["description"] = description + status_details = decode_cve_status(d, cve) + if 'detail' in status_details: + cve_item["detail"] = status_details['detail'] + if 'description' in status_details: + cve_item["description"] = status_details['description'] cve_list.append(cve_item) package_data["issue"] = cve_list diff --git a/meta/lib/oe/cve_check.py b/meta/lib/oe/cve_check.py index 7c09b78242..767d1a6750 100644 --- a/meta/lib/oe/cve_check.py +++ b/meta/lib/oe/cve_check.py @@ -132,8 +132,8 @@ def get_patched_cves(d): # Search for additional patched CVEs for cve in (d.getVarFlags("CVE_STATUS") or {}): - decoded_status, _, _ = decode_cve_status(d, cve) - if decoded_status == "Patched": + decoded_status = decode_cve_status(d, cve) + if 'mapping' in decoded_status and decoded_status['mapping'] == "Patched": bb.debug(2, "CVE %s is additionally patched" % cve) patched_cves.add(cve) @@ -227,22 +227,43 @@ def convert_cve_version(version): def decode_cve_status(d, cve): """ - Convert CVE_STATUS into status, detail and description. + Convert CVE_STATUS into status, vendor, product, detail and description. """ status = d.getVarFlag("CVE_STATUS", cve) if not status: - return ("", "", "") + return {} + + status_split = status.split(':', 5) + status_out = {} + status_out["detail"] = status_split[0] + product = "*" + vendor = "*" + description = "" + if len(status_split) >= 4 and status_split[1].strip() == "cpe": + # Both vendor and product are mandatory if cpe: present, the syntax is then: + # detail: cpe:vendor:product:description + vendor = status_split[2].strip() + product = status_split[3].strip() + description = status_split[4].strip() + elif len(status_split) >= 2 and status_split[1].strip() == "cpe": + # Malformed CPE + bb.warn('Invalid CPE information for CVE_STATUS[%s] = "%s", not setting CPE' % (detail, cve, status)) + else: + # Other case: no CPE, the syntax is then: + # detail: description + description = status_split[len(status_split)-1].strip() if (len(status_split) > 1) else "" - status_split = status.split(':', 1) - detail = status_split[0] - description = status_split[1].strip() if (len(status_split) > 1) else "" + status_out["vendor"] = vendor + status_out["product"] = product + status_out["description"] = description - status_mapping = d.getVarFlag("CVE_CHECK_STATUSMAP", detail) + status_mapping = d.getVarFlag("CVE_CHECK_STATUSMAP", status_out['detail']) if status_mapping is None: bb.warn('Invalid detail "%s" for CVE_STATUS[%s] = "%s", fallback to Unpatched' % (detail, cve, status)) status_mapping = "Unpatched" + status_out["mapping"] = status_mapping - return (status_mapping, detail, description) + return status_out def extend_cve_status(d): # do this only once in case multiple classes use this From patchwork Wed Mar 18 05:39:04 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Het Patel -X (hetpat - E INFOCHIPS PRIVATE LIMITED at Cisco)" X-Patchwork-Id: 83699 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 409D4FCD0B5 for ; Wed, 18 Mar 2026 05:39:17 +0000 (UTC) Received: from rcdn-iport-2.cisco.com (rcdn-iport-2.cisco.com [173.37.86.73]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.7581.1773812349558822087 for ; Tue, 17 Mar 2026 22:39:09 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="dkim: message contains an insecure body length tag" header.i=@cisco.com header.s=iport01 header.b=XDFNHWL3; spf=pass (domain: cisco.com, ip: 173.37.86.73, mailfrom: hetpat@cisco.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=19067; q=dns/txt; s=iport01; t=1773812349; x=1775021949; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=+6a8f8QOZjHnH8QFA6HcYnWOct2WlK9bSmQOd7nhAZs=; b=XDFNHWL3TYLbTXhW8KxV1m39Dgb4NEYzM2UYpjVR3sZ1PFPRBNAkTsqN Iiz5OsCru6FmHzCO/Yo3nv5E2iRCL7DbE0R149hwdC/BpacQgjfsQ0Kae xOAsvFOWaY2W5iCZNu68PnLR2EaixoDGU6bYIG9j5CS+6oOV7Dokor72y 4DQ9BxvwbKEKC6A6btoZ2XOrQoMxkMCGwp/KBMZm0hXz30/IsRqRi12OH LKkwkE5SrZLSbm6WnIISFWWWCIcm3aZtKnTpIHO2sqvB4Z67TG2p7ZA1H aQ8bwF/LqD0Tle+SMdXjp+9zw1DyDmjWL5p4H9osNiCz6Es2AyVUYPqQ+ g==; X-CSE-ConnectionGUID: 3Z3syOXpTeCLSbvDTyKwgA== X-CSE-MsgGUID: jvgfFSsUTDagafskfeS5pA== X-IPAS-Result: A0D5BQA1Obpp/5EQJK1aglmCGDAPcV9CSZZLA4tkkjaBfw8BAQEPNxoEAQGFBwKNIgImNAkOAQIEAQEBAQMCAwEBAQEBAQEBAQEBCwEBBQEBAQIBBwWBDhOGFQEGMw2GWwIBAzIBRhAgMSALKxmDAgGCOgM2AgGzDoIsgQGCZoIW2EcNglIBBQYUAYE4hTyCeYUgWhqEeicbG4FyhH2CH0IBiCUEgiKBDoF/h0eCADuGe0iBHgNZLAFVEw0KCwcFgWYDNRIqFW4yHYEjPheBCxsHBYQAD4htdG2BE4QMAwsYDUgRLDcUGwQ+bgeNTzuBQXIBASxFDQUKASsEARswKxYKBUwBGDo4A5JDLioTj1eCIZ9QTXEKKIN0jB6PPoV8GjOEBKZnmQaCWIsxhAmSR4RogWg8RoEBCwdwFTuCZ1IZD4d/AYdVAQeEQ8QCIzU9AQEHAgcNAwuBaJF9AQE IronPort-Data: A9a23:slAe9q/f8j10iJhhK+mCDrUD1H+TJUtcMsCJ2f8bNWPcYEJGY0x3m 2oeDGyAO/qJZWqjf913PIiw8kMGvsXTztcwGgZu+CBEQiMRo6IpJzg2wmQcns+2BpeeJK6yx 5xGMrEsFOhtEDmE4EzrauS9xZVF/fngbqLmD+LZMTxGSwZhSSMw4TpugOdRbrRA2bBVOCvT/ 4mpyyHjEAX9gWAsaTtLs/jrRC5H5ZwehhtJ5jTSWtgT1LPuvyF9JI4SI6i3M0z5TuF8dsamR /zOxa2O5WjQ+REgELuNyt4XpWVTH9Y+lSDX4pZnc/DKbipq/0Te4Y5nXBYoUnq7vh3S9zxHJ HqhgrTrIeshFvWkdO3wyHC0GQkmVUFN0OevzXRSLaV/wmWeG0YAzcmCA2ltD9YD68FHGV1D3 tgjIi4hUgGgmO2flefTpulE3qzPLeHiOIcZ/3UlxjbDALN+EdbIQr7B4plT2zJYasJmRKmFI ZFHL2MxKk2cPnWjOX9PYH46tOelmmH2bxVTqUmeouw85G27IAlZjOS9b4OLK4faLSlTtkSGq WzoxH/EPj0TO9WR0jmL/0nxnsaayEsXX6pXTtVU7MVCh0WewGEWAhAaWVa35PK+kEOWX9NEN 1dS/TIjq6U3/kGnQtTxGRqirxa5UgU0Ut5UFag+rQqK0KeRu1bfDWkfRTkHY9sj3CMreQEXO payt4uBLVRSXHe9ExpxKp/8QeuOBBUo IronPort-HdrOrdr: A9a23:MO/6lK1owCf6IlDy4l6gYAqjBLUkLtp133Aq2lEZdPWaSKOlfq eV7ZMmPHDP6Qr5NEtMpTnEAtjjfZq+z+8Q3WBuB9eftWDd0QPCRr2Kr7GSpgEIcBeRygcy78 tdmtBFeb7N5ZwQt7eC3OF+eOxQpuW6zA== X-Talos-CUID: 9a23:rBWlW28DCs2iFGyaQNyVvxUmQds0VU3F8Hr7B3SyF0pVWZ6KRnbFrQ== X-Talos-MUID: 9a23:OEwk8gxHFGqCd5oujd47okAcZEeaqKawB04jqo47h+WNOiV+IDSTgQ/qWqZyfw== X-IronPort-Anti-Spam-Filtered: true X-IronPort-AV: E=Sophos;i="6.23,126,1770595200"; d="scan'208";a="448716938" Received: from alln-l-core-08.cisco.com ([173.36.16.145]) by rcdn-iport-2.cisco.com with ESMTP/TLS/TLS_AES_256_GCM_SHA384; 18 Mar 2026 05:39:08 +0000 Received: from sjc-ads-8556.cisco.com (sjc-ads-8556.cisco.com [171.68.222.95]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by alln-l-core-08.cisco.com (Postfix) with ESMTPS id 49B5E1800022B; Wed, 18 Mar 2026 05:39:08 +0000 (GMT) Received: by sjc-ads-8556.cisco.com (Postfix, from userid 1847788) id E6231CE2A79; Tue, 17 Mar 2026 22:39:07 -0700 (PDT) From: "Het Patel -X (hetpat - E INFOCHIPS PRIVATE LIMITED at Cisco)" To: openembedded-core@lists.openembedded.org Cc: xe-linux-external@cisco.com, vchavda@cisco.com Subject: [OE-core] [scarthgap] [PATCH v1 2/4] cve-check: annotate CVEs during analysis Date: Tue, 17 Mar 2026 22:39:04 -0700 Message-Id: <20260318053906.26606-3-hetpat@cisco.com> X-Mailer: git-send-email 2.35.6 In-Reply-To: <20260318053906.26606-1-hetpat@cisco.com> References: <20260318053906.26606-1-hetpat@cisco.com> MIME-Version: 1.0 X-Outbound-SMTP-Client: 171.68.222.95, sjc-ads-8556.cisco.com X-Outbound-Node: alln-l-core-08.cisco.com List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 18 Mar 2026 05:39:17 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/233361 From: Marta Rybczynska Add status information for each CVE under analysis. Previously the information passed between different function of the cve-check class included only tables of patched, unpatched, ignored vulnerabilities and the general status of the recipe. The VEX work requires more information, and we need to pass them between different functions, so that it can be enriched as the analysis progresses. Instead of multiple tables, use a single one with annotations for each CVE encountered. For example, a patched CVE will have: {"abbrev-status": "Patched", "status": "version-not-in-range"} abbrev-status contains the general status (Patched, Unpatched, Ignored and Unknown that will be added in the VEX code) status contains more detailed information that can come from CVE_STATUS and the analysis. Additional fields of the annotation include for example the name of the patch file fixing a given CVE. We also use the annotation in CVE_STATUS to filter out entries that do not apply to the given recipe Backport Changes: - Cherry-picking this patch, which precedes commit [358dbfcd80ae] in master. Since commit [358dbfcd80ae] was already cherry-picked earlier in scarthgap, adjusted the changes accordingly to avoid conflicts. Signed-off-by: Marta Rybczynska Signed-off-by: Samantha Jalabert Signed-off-by: Richard Purdie (cherry picked from commit 452e605b55ad61c08f4af7089a5a9c576ca28f7d) Signed-off-by: Het Patel --- meta/classes/cve-check.bbclass | 214 +++++++++++++++++---------------- meta/lib/oe/cve_check.py | 35 +++++- 2 files changed, 142 insertions(+), 107 deletions(-) diff --git a/meta/classes/cve-check.bbclass b/meta/classes/cve-check.bbclass index de5ddf6f04..32fb9e8a5c 100644 --- a/meta/classes/cve-check.bbclass +++ b/meta/classes/cve-check.bbclass @@ -176,10 +176,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) + cve_data, status = check_cves(d, patched_cves) + if len(cve_data) or (d.getVar("CVE_CHECK_COVERAGE") == "1" and status): + get_cve_info(d, cve_data) + cve_write_data(d, cve_data, status) else: bb.note("No CVE database found, skipping CVE check") @@ -287,7 +287,51 @@ ROOTFS_POSTPROCESS_COMMAND:prepend = "${@'cve_check_write_rootfs_manifest ' if d do_rootfs[recrdeptask] += "${@'do_cve_check' if d.getVar('CVE_CHECK_CREATE_MANIFEST') == '1' else ''}" do_populate_sdk[recrdeptask] += "${@'do_cve_check' if d.getVar('CVE_CHECK_CREATE_MANIFEST') == '1' else ''}" -def check_cves(d, patched_cves): +def cve_is_ignored(d, cve_data, cve): + if cve not in cve_data: + return False + if cve_data[cve]['abbrev-status'] == "Ignored": + return True + return False + +def cve_is_patched(d, cve_data, cve): + if cve not in cve_data: + return False + if cve_data[cve]['abbrev-status'] == "Patched": + return True + return False + +def cve_update(d, cve_data, cve, entry): + # If no entry, just add it + if cve not in cve_data: + cve_data[cve] = entry + return + # If we are updating, there might be change in the status + bb.debug("Trying CVE entry update for %s from %s to %s" % (cve, cve_data[cve]['abbrev-status'], entry['abbrev-status'])) + if cve_data[cve]['abbrev-status'] == "Unknown": + cve_data[cve] = entry + return + if cve_data[cve]['abbrev-status'] == entry['abbrev-status']: + return + # Update like in {'abbrev-status': 'Patched', 'status': 'version-not-in-range'} to {'abbrev-status': 'Unpatched', 'status': 'version-in-range'} + if entry['abbrev-status'] == "Unpatched" and cve_data[cve]['abbrev-status'] == "Patched": + if entry['status'] == "version-in-range" and cve_data[cve]['status'] == "version-not-in-range": + # New result from the scan, vulnerable + cve_data[cve] = entry + bb.debug("CVE entry %s update from Patched to Unpatched from the scan result" % cve) + return + if entry['abbrev-status'] == "Patched" and cve_data[cve]['abbrev-status'] == "Unpatched": + if entry['status'] == "version-not-in-range" and cve_data[cve]['status'] == "version-in-range": + # Range does not match the scan, but we already have a vulnerable match, ignore + bb.debug("CVE entry %s update from Patched to Unpatched from the scan result - not applying" % cve) + return + # If we have an "Ignored", it has a priority + if cve_data[cve]['abbrev-status'] == "Ignored": + bb.debug("CVE %s not updating because Ignored" % cve) + return + bb.warn("Unhandled CVE entry update for %s from %s to %s" % (cve, cve_data[cve], entry)) + +def check_cves(d, cve_data): """ Connect to the NVD database and find unpatched cves. """ @@ -297,28 +341,19 @@ def check_cves(d, patched_cves): real_pv = d.getVar("PV") suffix = d.getVar("CVE_VERSION_SUFFIX") - cves_unpatched = [] - cves_ignored = [] cves_status = [] cves_in_recipe = False # CVE_PRODUCT can contain more than one product (eg. curl/libcurl) 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 ([], [], [], []) - - # Convert CVE_STATUS into ignored CVEs and check validity - cve_ignore = [] - for cve in (d.getVarFlags("CVE_STATUS") or {}): - decoded_status = decode_cve_status(d, cve) - if 'mapping' in decoded_status and decoded_status['mapping'] == "Ignored": - cve_ignore.append(cve) + return ([], []) import sqlite3 db_file = d.expand("file:${CVE_CHECK_DB_FILE}?mode=ro") @@ -337,11 +372,10 @@ def check_cves(d, patched_cves): for cverow in cve_cursor: cve = cverow[0] - if cve in cve_ignore: + if cve_is_ignored(d, cve_data, cve): bb.note("%s-%s ignores %s" % (product, pv, cve)) - cves_ignored.append(cve) continue - elif cve in patched_cves: + elif cve_is_patched(d, cve_data, cve): bb.note("%s has been patched" % (cve)) continue # Write status once only for each product @@ -357,7 +391,7 @@ def check_cves(d, patched_cves): for row in product_cursor: (_, _, _, version_start, operator_start, version_end, operator_end) = row #bb.debug(2, "Evaluating row " + str(row)) - if cve in cve_ignore: + if cve_is_ignored(d, cve_data, cve): ignored = True version_start = convert_cve_version(version_start) @@ -396,16 +430,16 @@ def check_cves(d, patched_cves): if vulnerable: if ignored: bb.note("%s is ignored in %s-%s" % (cve, pn, real_pv)) - cves_ignored.append(cve) + cve_update(d, cve_data, cve, {"abbrev-status": "Ignored"}) else: bb.note("%s-%s is vulnerable to %s" % (pn, real_pv, cve)) - cves_unpatched.append(cve) + cve_update(d, cve_data, cve, {"abbrev-status": "Unpatched", "status": "version-in-range"}) break product_cursor.close() if not vulnerable: bb.note("%s-%s is not vulnerable to %s" % (pn, real_pv, cve)) - patched_cves.add(cve) + cve_update(d, cve_data, cve, {"abbrev-status": "Patched", "status": "version-not-in-range"}) cve_cursor.close() if not cves_in_product: @@ -413,49 +447,46 @@ def check_cves(d, patched_cves): cves_status.append([product, False]) conn.close() - diff_ignore = list(set(cve_ignore) - set(cves_ignored)) - if diff_ignore: - oe.qa.handle_error("cve_status_not_in_db", "Found CVE (%s) with CVE_STATUS set that are not found in database for this component" % " ".join(diff_ignore), d) 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 (cve_data, cves_status) -def get_cve_info(d, cves): +def get_cve_info(d, cve_data): """ Get CVE information from the database. """ import sqlite3 - cve_data = {} db_file = d.expand("file:${CVE_CHECK_DB_FILE}?mode=ro") conn = sqlite3.connect(db_file, uri=True) - for cve in cves: + for cve in cve_data: cursor = conn.execute("SELECT * FROM NVD WHERE ID IS ?", (cve,)) for row in cursor: - cve_data[row[0]] = {} - cve_data[row[0]]["summary"] = row[1] - cve_data[row[0]]["scorev2"] = row[2] - cve_data[row[0]]["scorev3"] = row[3] - cve_data[row[0]]["scorev4"] = row[4] - cve_data[row[0]]["modified"] = row[5] - cve_data[row[0]]["vector"] = row[6] - cve_data[row[0]]["vectorString"] = row[7] + # The CVE itdelf has been added already + if row[0] not in cve_data: + bb.note("CVE record %s not present" % row[0]) + continue + #cve_data[row[0]] = {} + cve_data[row[0]]["NVD-summary"] = row[1] + cve_data[row[0]]["NVD-scorev2"] = row[2] + cve_data[row[0]]["NVD-scorev3"] = row[3] + cve_data[row[0]]["NVD-scorev4"] = row[4] + cve_data[row[0]]["NVD-modified"] = row[5] + cve_data[row[0]]["NVD-vector"] = row[6] + cve_data[row[0]]["NVD-vectorString"] = row[7] cursor.close() conn.close() - return cve_data -def cve_write_data_text(d, patched, unpatched, ignored, cve_data): +def cve_write_data_text(d, cve_data): """ Write CVE information in WORKDIR; and to CVE_CHECK_DIR, and CVE manifest if enabled. """ - from oe.cve_check import decode_cve_status - cve_file = d.getVar("CVE_CHECK_LOG") fdir_name = d.getVar("FILE_DIRNAME") layer = fdir_name.split("/")[-3] @@ -472,7 +503,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 len(cve_data): return nvd_link = "https://nvd.nist.gov/vuln/detail/" @@ -481,37 +512,30 @@ def cve_write_data_text(d, patched, unpatched, ignored, cve_data): bb.utils.mkdirhier(os.path.dirname(cve_file)) for cve in sorted(cve_data): - is_patched = cve in patched - is_ignored = cve in ignored - - status = "Unpatched" - if (is_patched or is_ignored) and not report_all: + if not report_all and (cve_data[cve]["abbrev-status"] == "Patched" or cve_data[cve]["abbrev-status"] == "Ignored"): continue - if is_ignored: - status = "Ignored" - elif is_patched: - status = "Patched" - else: - # default value of status is Unpatched - unpatched_cves.append(cve) - write_string += "LAYER: %s\n" % layer write_string += "PACKAGE NAME: %s\n" % d.getVar("PN") write_string += "PACKAGE VERSION: %s%s\n" % (d.getVar("EXTENDPE"), d.getVar("PV")) write_string += "CVE: %s\n" % cve - write_string += "CVE STATUS: %s\n" % status - status_details = decode_cve_status(d, cve) - if 'detail' in status_details: - write_string += "CVE DETAIL: %s\n" % status_details['detail'] - if 'description' in status_details: - write_string += "CVE DESCRIPTION: %s\n" % status_details['description'] - write_string += "CVE SUMMARY: %s\n" % cve_data[cve]["summary"] - write_string += "CVSS v2 BASE SCORE: %s\n" % cve_data[cve]["scorev2"] - write_string += "CVSS v3 BASE SCORE: %s\n" % cve_data[cve]["scorev3"] - write_string += "CVSS v4 BASE SCORE: %s\n" % cve_data[cve]["scorev4"] - write_string += "VECTOR: %s\n" % cve_data[cve]["vector"] - write_string += "VECTORSTRING: %s\n" % cve_data[cve]["vectorString"] + write_string += "CVE STATUS: %s\n" % cve_data[cve]["abbrev-status"] + + if 'status' in cve_data[cve]: + write_string += "CVE DETAIL: %s\n" % cve_data[cve]["status"] + if 'justification' in cve_data[cve]: + write_string += "CVE DESCRIPTION: %s\n" % cve_data[cve]["justification"] + + if "NVD-summary" in cve_data[cve]: + write_string += "CVE SUMMARY: %s\n" % cve_data[cve]["NVD-summary"] + write_string += "CVSS v2 BASE SCORE: %s\n" % cve_data[cve]["NVD-scorev2"] + write_string += "CVSS v3 BASE SCORE: %s\n" % cve_data[cve]["NVD-scorev3"] + write_string += "CVSS v3 BASE SCORE: %s\n" % cve_data[cve]["NVD-scorev4"] + write_string += "VECTOR: %s\n" % cve_data[cve]["NVD-vector"] + write_string += "VECTORSTRING: %s\n" % cve_data[cve]["NVD-vectorString"] + write_string += "MORE INFORMATION: %s%s\n\n" % (nvd_link, cve) + if cve_data[cve]["abbrev-status"] == "Unpatched": + unpatched_cves.append(cve) if unpatched_cves and d.getVar("CVE_CHECK_SHOW_WARNINGS") == "1": bb.warn("Found unpatched CVE (%s), for more information check %s" % (" ".join(unpatched_cves),cve_file)) @@ -563,13 +587,11 @@ 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, cve_data, cve_status): """ Prepare CVE data for the JSON format, then write it. """ - from oe.cve_check import decode_cve_status - output = {"version":"1", "package": []} nvd_link = "https://nvd.nist.gov/vuln/detail/" @@ -587,8 +609,6 @@ def cve_write_data_json(d, patched, unpatched, ignored, cve_data, cve_status): if include_layers and layer not in include_layers: return - unpatched_cves = [] - product_data = [] for s in cve_status: p = {"product": s[0], "cvesInRecord": "Yes"} @@ -603,40 +623,32 @@ def cve_write_data_json(d, patched, unpatched, ignored, cve_data, cve_status): "version" : package_version, "products": product_data } + cve_list = [] for cve in sorted(cve_data): - is_patched = cve in patched - is_ignored = cve in ignored - status = "Unpatched" - if (is_patched or is_ignored) and not report_all: + if not report_all and (cve_data[cve]["abbrev-status"] == "Patched" or cve_data[cve]["abbrev-status"] == "Ignored"): continue - if is_ignored: - status = "Ignored" - elif is_patched: - status = "Patched" - else: - # default value of status is Unpatched - unpatched_cves.append(cve) - issue_link = "%s%s" % (nvd_link, cve) cve_item = { "id" : cve, - "summary" : cve_data[cve]["summary"], - "scorev2" : cve_data[cve]["scorev2"], - "scorev3" : cve_data[cve]["scorev3"], - "scorev4" : cve_data[cve]["scorev4"], - "vector" : cve_data[cve]["vector"], - "vectorString" : cve_data[cve]["vectorString"], - "status" : status, - "link": issue_link + "status" : cve_data[cve]["abbrev-status"], + "link": issue_link, } - status_details = decode_cve_status(d, cve) - if 'detail' in status_details: - cve_item["detail"] = status_details['detail'] - if 'description' in status_details: - cve_item["description"] = status_details['description'] + if 'NVD-summary' in cve_data[cve]: + cve_item["summary"] = cve_data[cve]["NVD-summary"] + cve_item["scorev2"] = cve_data[cve]["NVD-scorev2"] + cve_item["scorev3"] = cve_data[cve]["NVD-scorev3"] + cve_item["scorev4"] = cve_data[cve]["NVD-scorev4"] + cve_item["vector"] = cve_data[cve]["NVD-vector"] + cve_item["vectorString"] = cve_data[cve]["NVD-vectorString"] + if 'status' in cve_data[cve]: + cve_item["detail"] = cve_data[cve]["status"] + if 'justification' in cve_data[cve]: + cve_item["description"] = cve_data[cve]["justification"] + if 'resource' in cve_data[cve]: + cve_item["patch-file"] = cve_data[cve]["resource"] cve_list.append(cve_item) package_data["issue"] = cve_list @@ -648,12 +660,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, 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, 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, cve_data, status) diff --git a/meta/lib/oe/cve_check.py b/meta/lib/oe/cve_check.py index 767d1a6750..37230b7957 100644 --- a/meta/lib/oe/cve_check.py +++ b/meta/lib/oe/cve_check.py @@ -88,7 +88,7 @@ def get_patched_cves(d): # (cve_match regular expression) cve_file_name_match = re.compile(r".*(CVE-\d{4}-\d+)", re.IGNORECASE) - patched_cves = set() + patched_cves = {} patches = oe.patch.src_patches(d) bb.debug(2, "Scanning %d patches for CVEs" % len(patches)) for url in patches: @@ -98,7 +98,7 @@ def get_patched_cves(d): fname_match = cve_file_name_match.search(patch_file) if fname_match: cve = fname_match.group(1).upper() - patched_cves.add(cve) + patched_cves[cve] = {"abbrev-status": "Patched", "status": "fix-file-included", "resource": patch_file} bb.debug(2, "Found %s from patch file name %s" % (cve, patch_file)) # Remote patches won't be present and compressed patches won't be @@ -124,7 +124,7 @@ def get_patched_cves(d): cves = patch_text[match.start()+5:match.end()] for cve in cves.split(): bb.debug(2, "Patch %s solves %s" % (patch_file, cve)) - patched_cves.add(cve) + patched_cves[cve] = {"abbrev-status": "Patched", "status": "fix-file-included", "resource": patch_file} text_match = True if not fname_match and not text_match: @@ -133,9 +133,15 @@ def get_patched_cves(d): # Search for additional patched CVEs for cve in (d.getVarFlags("CVE_STATUS") or {}): decoded_status = decode_cve_status(d, cve) - if 'mapping' in decoded_status and decoded_status['mapping'] == "Patched": - bb.debug(2, "CVE %s is additionally patched" % cve) - patched_cves.add(cve) + products = d.getVar("CVE_PRODUCT") + if has_cve_product_match(decoded_status, products) == True: + patched_cves[cve] = { + "abbrev-status": decoded_status["mapping"], + "status": decoded_status["detail"], + "justification": decoded_status["description"], + "affected-vendor": decoded_status["vendor"], + "affected-product": decoded_status["product"] + } return patched_cves @@ -286,3 +292,20 @@ def extend_cve_status(d): d.setVarFlag("CVE_STATUS", cve, d.getVarFlag(cve_status_group, "status")) else: bb.warn("CVE_STATUS_GROUPS contains undefined variable %s" % cve_status_group) + +def has_cve_product_match(detailed_status, products): + """ + Check product/vendor match between detailed_status from decode_cve_status and a string of + products (like from CVE_PRODUCT) + """ + for product in products.split(): + vendor = "*" + if ":" in product: + vendor, product = product.split(":", 1) + + if (vendor == detailed_status["vendor"] or detailed_status["vendor"] == "*") and \ + (product == detailed_status["product"] or detailed_status["product"] == "*"): + return True + + #if no match, return False + return False From patchwork Wed Mar 18 05:39:05 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Het Patel -X (hetpat - E INFOCHIPS PRIVATE LIMITED at Cisco)" X-Patchwork-Id: 83696 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 335E4FCD0B4 for ; Wed, 18 Mar 2026 05:39:17 +0000 (UTC) Received: from rcdn-iport-8.cisco.com (rcdn-iport-8.cisco.com [173.37.86.79]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.7591.1773812349398889198 for ; Tue, 17 Mar 2026 22:39:09 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="dkim: message contains an insecure body length tag" header.i=@cisco.com header.s=iport01 header.b=A62EaP50; spf=pass (domain: cisco.com, ip: 173.37.86.79, mailfrom: hetpat@cisco.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=2535; q=dns/txt; s=iport01; t=1773812349; x=1775021949; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=O8SR6U+bdA1Wp2hQ9N7Qf1aCBSztoRgEJvHWKiEOFaA=; b=A62EaP50w8yYyP1OqFDwp+XgqRpfjID4gAVnF+OGinFUGAitcgK9L95H Uu2DdtNlHUaavhNxtnO5KwL4JrKY6dEq2JSNXlkcwlVPNx+xMe6L8laA4 7F7qp4kxGp+eA113t49Dmf89j+jDOin7/IiZyHThI3I7c3WgzWKWZn3FG 2Qj7AMk91IagESGrIL6zeeXwJfEX41/9jlX1tH5MhEVK9DlLfWjkVx5VG 2lQ8+lzp4phsCnqVuGXghuW88ndFpNBIeNDweoQC4ver1CWIz60TOSb9k /BefF5CGKlLA+R85G3cD0mYU42E8v2sD73LaBLq4PHqFTPNM5yYWPlmrE A==; X-CSE-ConnectionGUID: pEinnSt3TBC4eotn9E5zAQ== X-CSE-MsgGUID: T6V3JBhGRk66gvZD6JSR+Q== X-IPAS-Result: A0DzBQCqObpp/4oQJK1aHgEBCxIMggULgkgPgVBCSZZLA4tkkjaBfw8BAQEPUQQBAYUHAo0iAiY0CQ4BAgQBAQEBAwIDAQEBAQEBAQEBAQELAQEFAQEBAgEHBYEOE4ZchlsCAQMyAUYQIDEgCysZgwKCOwM2AgGzDoIsgQGEfNhHDYJSAQsUAYE4hTyCeYUgWhqEeicbG4FyhAd2gh+CcYV3BIIigQ6SfEiBHgNZLAFVEw0KCwcFgWYDNRIqFW4yHYEjPheBCxsHBYQAD4htdG2BE4QMAwsYDUgRLDcUGwQ+bgeNTzuCADQBHjQ7RWynG6AdcQoog3SbXIV8GjOqa5kGkhKSR4RogWg8gVlwFYMiUhkP2BQjNT0CBwIHDQMLk2UBAQ IronPort-Data: A9a23:pSon/a11Jvn/nbo9PPbD5Ydwkn2cJEfYwER7XKvMYLTBsI5bp2QGn zYfDG+CPvrbNDOmeY92aIu190tSu5SEx9JnGgY53Hw8FHgiRegpqji6wuYcGwvIc6UvmWo+t 512huHodZ5yFjmH4E/xbtANlFEkvYmQXL3wFeXYDS54QA5gWU8JhAlq8wIDqtYAbeORXUXX4 rsen+WFYAX7g2UtbTpOg06+gEoHUMra6WtwUmMWPZinjHeG/1EJAZQWI72GLneQauF8Au6gS u/f+6qy92Xf8g1FIovNfmHTKxBirhb6ZGBiu1IOM0SQqkEqSh8ajs7XAMEhhXJ/0F1lqTzeJ OJl7vRcQS9xVkHFdX90vxNwS0mSNoUekFPLzOTWXcG7lyX7n3XQL/pGFGw3O4sj5r1LK0oS+ PsELmEgMwKqvrfjqF67YrEEasULJc3vOsYb/3pn1zycVa9gSpHYSKKM7thdtNsyrpkRRrCFO YxAN3w2N0Sojx5nYj/7DLo+kfuwj2XXeDxDo1XTrq0yi4TW5FAsjOC2bYSPIbRmQ+1pwHjDh EjG0F76XE8VKu6zlxi+yDGV07qncSTTHdh6+KeD3vlyjVuew2YeBBEbWR6wpuO0okq/QM5Eb UsM9ywjqKI/+ECmQp/6RRLQnZKflhcYX9wVF6gx7xuAj/KNpQ2YHWMDCDVGbbTKqfMLeNDj7 XfR9/uBONClmOf9pa61nltMkQ6PBA== IronPort-HdrOrdr: A9a23:CXyNAKAc+Q1NEuPlHemr55DYdb4zR+YMi2TDGXofdfUzSL3+qy nAppUmPHPP5Qr5HUtQ++xoW5PwJU80i6QU3WB5B97LN2PbUSmTXeRfBODZrQEIdReTygck79 YCT0C7Y+eAdGSTSq3BkW+FL+o= X-Talos-CUID: 9a23:kx/qjmHXy5eBJcR/qmJ/2U8SHPs5KUH35yvdJFO+WEs0WpSsHAo= X-Talos-MUID: 9a23:8B8YwwrCyS/9/Yg6rGwezw08CpxKyaSBMkNTz5oYieXaFxdKeA7I2Q== X-IronPort-Anti-Spam-Filtered: true X-IronPort-AV: E=Sophos;i="6.23,126,1770595200"; d="scan'208";a="454035623" Received: from alln-l-core-01.cisco.com ([173.36.16.138]) by rcdn-iport-8.cisco.com with ESMTP/TLS/TLS_AES_256_GCM_SHA384; 18 Mar 2026 05:39:08 +0000 Received: from sjc-ads-8556.cisco.com (sjc-ads-8556.cisco.com [171.68.222.95]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by alln-l-core-01.cisco.com (Postfix) with ESMTPS id 508751800019B; Wed, 18 Mar 2026 05:39:08 +0000 (GMT) Received: by sjc-ads-8556.cisco.com (Postfix, from userid 1847788) id E9E78CE2A7A; Tue, 17 Mar 2026 22:39:07 -0700 (PDT) From: "Het Patel -X (hetpat - E INFOCHIPS PRIVATE LIMITED at Cisco)" To: openembedded-core@lists.openembedded.org Cc: xe-linux-external@cisco.com, vchavda@cisco.com Subject: [OE-core] [scarthgap] [PATCH v1 3/4] cve-check-map: add new statuses Date: Tue, 17 Mar 2026 22:39:05 -0700 Message-Id: <20260318053906.26606-4-hetpat@cisco.com> X-Mailer: git-send-email 2.35.6 In-Reply-To: <20260318053906.26606-1-hetpat@cisco.com> References: <20260318053906.26606-1-hetpat@cisco.com> MIME-Version: 1.0 X-Outbound-SMTP-Client: 171.68.222.95, sjc-ads-8556.cisco.com X-Outbound-Node: alln-l-core-01.cisco.com List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 18 Mar 2026 05:39:17 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/233360 From: Marta Rybczynska Add 'fix-file-included', 'version-not-in-range' and 'version-in-range' generated by the cve-check. 'fix-file-included' means that a fix file for the CVE has been located. 'version-not-in-range' means that the product version has been found outside of the vulnerable range. 'version-in-range' means that the product version has been found inside of the vulnerable range. Signed-off-by: Marta Rybczynska Signed-off-by: Samantha Jalabert Signed-off-by: Richard Purdie (cherry picked from commit d25f1817752bc8a84c40dcbef75f7559801ce15e) Signed-off-by: Het Patel --- meta/conf/cve-check-map.conf | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/meta/conf/cve-check-map.conf b/meta/conf/cve-check-map.conf index 17b0f15571..ac956379d1 100644 --- a/meta/conf/cve-check-map.conf +++ b/meta/conf/cve-check-map.conf @@ -8,11 +8,17 @@ CVE_CHECK_STATUSMAP[backported-patch] = "Patched" CVE_CHECK_STATUSMAP[cpe-stable-backport] = "Patched" # use when NVD DB does not mention correct version or does not mention any verion at all CVE_CHECK_STATUSMAP[fixed-version] = "Patched" +# use when a fix file has been included (set automatically) +CVE_CHECK_STATUSMAP[fix-file-included] = "Patched" +# do not use directly: automatic scan reports version number NOT in the vulnerable range (set automatically) +CVE_CHECK_STATUSMAP[version-not-in-range] = "Patched" # used internally by this class if CVE vulnerability is detected which is not marked as fixed or ignored CVE_CHECK_STATUSMAP[unpatched] = "Unpatched" # use when CVE is confirmed by upstream but fix is still not available CVE_CHECK_STATUSMAP[vulnerable-investigating] = "Unpatched" +# do not use directly: automatic scan reports version number IS in the vulnerable range (set automatically) +CVE_CHECK_STATUSMAP[version-in-range] = "Unpatched" # used for migration from old concept, do not use for new vulnerabilities CVE_CHECK_STATUSMAP[ignored] = "Ignored" @@ -26,3 +32,6 @@ CVE_CHECK_STATUSMAP[not-applicable-config] = "Ignored" CVE_CHECK_STATUSMAP[not-applicable-platform] = "Ignored" # use when upstream acknowledged the vulnerability but does not plan to fix it CVE_CHECK_STATUSMAP[upstream-wontfix] = "Ignored" + +# use when it is impossible to conclude if the vulnerability is present or not +CVE_CHECK_STATUSMAP[unknown] = "Unknown" From patchwork Wed Mar 18 05:39:06 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Het Patel -X (hetpat - E INFOCHIPS PRIVATE LIMITED at Cisco)" X-Patchwork-Id: 83697 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 68160FCD0B6 for ; Wed, 18 Mar 2026 05:39:17 +0000 (UTC) Received: from rcdn-iport-7.cisco.com (rcdn-iport-7.cisco.com [173.37.86.78]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.7592.1773812351113284123 for ; Tue, 17 Mar 2026 22:39:11 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="dkim: message contains an insecure body length tag" header.i=@cisco.com header.s=iport01 header.b=D451APU5; spf=pass (domain: cisco.com, ip: 173.37.86.78, mailfrom: hetpat@cisco.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=2360; q=dns/txt; s=iport01; t=1773812351; x=1775021951; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=5w9aO5h3SqwaHC66ykhefrYzQ+Z5hMC0pexYcmToKQ8=; b=D451APU5nFvz3DO8CXz4zD4OSYguxxKgFNIrTUcunj2QzK0aPhUOisWw 4w9QYh2SYaTB2E0rncKpozjYZAomCWHRYOF3YYZ8MvuGCuZUkJEY+eHHS vZ/OYH6bmfzqYc+a19Dro5QMmz6oNrLwm1KB+LFvz6Ei2YEDYhGG6z991 TZtXKDF2F9+bFHhw5X5jBwDZA3NTNqyDEXf5NMbn5T8INXV9WJh+vihzb JqZXBwcNgAAde3L94eC68b+KQX8l+gtlRm4jDu8WrXNwdvBVHDwipRLed ngVB+ccb+HHnuAlb6g3EaK+0sGC603y7LdxyehMlDtVo20q710kibBx8X g==; X-CSE-ConnectionGUID: 6vQJwWrDTKm7f3OOrA9E4w== X-CSE-MsgGUID: xBD9Zo33RQW8bct0XlYzSw== X-IPAS-Result: A0CMBQCqObpp/5AQJK1aglmCGDAPgVBCSZZLA54agX8PAQEBD1EEAQGFBwKNIgImNAkOAQIEAQEBAQMCAwEBAQEBAQEBAQEBCwEBBQEBAQIBBwWBDhOGXIZbAgEDMgFGECAxKysZgwKCdAIBsw6CLIEBhHzbJgELFAGBOIU8iBlaGoR6JxsbgXKEfYUQhXcEgiKBDpJ8SIEeA1ksAVUTDQoLBwWBZgM1EioVbjIdgSM+F4ELGwcFhAAPiG10bYEThAwDCxgNSBEsNxQbBD5uB41PO4IzAQGBDTCCO6VhoQ4KKIN0oVgaM4QEpmeZBoJYoUo3hGiBaDyBWXAVgyJSGQ+PVQEHyDcjNT0CBwIHDQMLk2UBAQ IronPort-Data: A9a23:729wyKujDSh9tS/oFr7kFtbdAOfnVAJfMUV32f8akzHdYApBsoF/q tZmKWCDOv7eZmSgf9hzbIm0/ENV75OGztRkGlA9+HozHnsVgMeUXt7xwmUckM+xwmwvaGo9s q3yv/GZdJhcokf0/0nrav666yEgiclkf5KkYMbcICd9WAR4fykojBNnioYRj5Vh6TSDK1vlV eja/YuFYzdJ5xYuajhKs/na90s11BjPkGpwUmIWNKgjUGD2zxH5PLpHTYmtIn3xRJVjH+LSb 47r0LGj82rFyAwmA9Wjn6yTWhVirmn6ZFXmZtJ+AsBOszAazsAA+v9T2Mk0NS+7vw60c+VZk 72hg3AfpTABZcUgkMxFO/VR/roX0aduoNcrKlDn2SCfItGvn3bEm51T4E8K0YIwpPhOI35x7 9AkCzVSYEukoPifkZ/nVbw57igjBJGD0II3s3Vky3TdSP0hW52GG/qM7t5D1zB2jcdLdRrcT 5NGMnw0MlKZPVsWZgt/5JEWxI9EglH/fiFAoU69rqss6G+Vxwt0uFToGIaLIIbRFZkNxS50o ErW1UioMBZBb+am9mqP+W70tuv+jxjkDdd6+LqQs6QCbEeo7msLBRsbUFG2rfW0hgu1XMhSA 0gV4TY1668q+UqmS9PwUxG1rDiDpBF0ZjZLO+Q+7AfIzu/f5ByUQzBbCDVAc9ch8sQxQFTGy 2O0oj8gPhQ32JX9dJ5X3uz8Qe+aUcTNEVI/WA== IronPort-HdrOrdr: A9a23:3AR2H6mBPD6BDXIhQT7JdCx3TEbpDfIr3DAbv31ZSRFFG/FwWf rAoB19726StN9/YhAdcLy7VZVoBEmsl6KdgrNhWYtKIjOHhILAFugLhuHfKn/bakjDH4Vmu5 uIHZITNDSJNykYsS4/izPIaurJB7K8gcaVuds= X-Talos-CUID: 9a23:4FJB926z263bGNJqtNssqlAtON8aaFHh73KPLRSfLnxAGZDJVgrF X-Talos-MUID: 9a23:+Y2Kow74X6IDid4Vm3tmJfM0xox4yYj/OkdWyq8/hJmOPjAoCzOsng+oF9o= X-IronPort-Anti-Spam-Filtered: true X-IronPort-AV: E=Sophos;i="6.23,126,1770595200"; d="scan'208";a="462238403" Received: from alln-l-core-07.cisco.com ([173.36.16.144]) by rcdn-iport-7.cisco.com with ESMTP/TLS/TLS_AES_256_GCM_SHA384; 18 Mar 2026 05:39:08 +0000 Received: from sjc-ads-8556.cisco.com (sjc-ads-8556.cisco.com [171.68.222.95]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by alln-l-core-07.cisco.com (Postfix) with ESMTPS id 5221D18000365; Wed, 18 Mar 2026 05:39:08 +0000 (GMT) Received: by sjc-ads-8556.cisco.com (Postfix, from userid 1847788) id ED8B8CE2A7B; Tue, 17 Mar 2026 22:39:07 -0700 (PDT) From: "Het Patel -X (hetpat - E INFOCHIPS PRIVATE LIMITED at Cisco)" To: openembedded-core@lists.openembedded.org Cc: xe-linux-external@cisco.com, vchavda@cisco.com Subject: [OE-core] [scarthgap] [PATCH v1 4/4] cve-check: fix debug message Date: Tue, 17 Mar 2026 22:39:06 -0700 Message-Id: <20260318053906.26606-5-hetpat@cisco.com> X-Mailer: git-send-email 2.35.6 In-Reply-To: <20260318053906.26606-1-hetpat@cisco.com> References: <20260318053906.26606-1-hetpat@cisco.com> MIME-Version: 1.0 X-Outbound-SMTP-Client: 171.68.222.95, sjc-ads-8556.cisco.com X-Outbound-Node: alln-l-core-07.cisco.com List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 18 Mar 2026 05:39:17 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/233363 From: Daniel Turull Debug level was not added as a parameter, causing a warning. Signed-off-by: Daniel Turull Signed-off-by: Richard Purdie (cherry picked from commit 40157fcbd9066f261812ba665ec963b2e496aa53) Signed-off-by: Het Patel --- meta/classes/cve-check.bbclass | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/meta/classes/cve-check.bbclass b/meta/classes/cve-check.bbclass index 32fb9e8a5c..d84fe2a0d3 100644 --- a/meta/classes/cve-check.bbclass +++ b/meta/classes/cve-check.bbclass @@ -307,7 +307,7 @@ def cve_update(d, cve_data, cve, entry): cve_data[cve] = entry return # If we are updating, there might be change in the status - bb.debug("Trying CVE entry update for %s from %s to %s" % (cve, cve_data[cve]['abbrev-status'], entry['abbrev-status'])) + bb.debug(1, "Trying CVE entry update for %s from %s to %s" % (cve, cve_data[cve]['abbrev-status'], entry['abbrev-status'])) if cve_data[cve]['abbrev-status'] == "Unknown": cve_data[cve] = entry return @@ -318,16 +318,16 @@ def cve_update(d, cve_data, cve, entry): if entry['status'] == "version-in-range" and cve_data[cve]['status'] == "version-not-in-range": # New result from the scan, vulnerable cve_data[cve] = entry - bb.debug("CVE entry %s update from Patched to Unpatched from the scan result" % cve) + bb.debug(1, "CVE entry %s update from Patched to Unpatched from the scan result" % cve) return if entry['abbrev-status'] == "Patched" and cve_data[cve]['abbrev-status'] == "Unpatched": if entry['status'] == "version-not-in-range" and cve_data[cve]['status'] == "version-in-range": # Range does not match the scan, but we already have a vulnerable match, ignore - bb.debug("CVE entry %s update from Patched to Unpatched from the scan result - not applying" % cve) + bb.debug(1, "CVE entry %s update from Patched to Unpatched from the scan result - not applying" % cve) return # If we have an "Ignored", it has a priority if cve_data[cve]['abbrev-status'] == "Ignored": - bb.debug("CVE %s not updating because Ignored" % cve) + bb.debug(1, "CVE %s not updating because Ignored" % cve) return bb.warn("Unhandled CVE entry update for %s from %s to %s" % (cve, cve_data[cve], entry))