| Message ID | 20260113070840.115911-1-hetpat@cisco.com |
|---|---|
| State | Rejected, archived |
| Delegated to: | Yoann Congal |
| Headers | show |
| Series | [scarthgap] Fix CVE CVSS scoring to use maximum score from all sources | expand |
Le mar. 13 janv. 2026 à 08:08, Het Patel via lists.openembedded.org <hetpat= cisco.com@lists.openembedded.org> a écrit : > From: Het Patel <hetpat@cisco.com> > > The CVE check system was incorrectly reporting lower CVSS scores when > multiple scoring sources were available in the NVD database. This > occurred because the code only extracted the first element from the > CVSSv2, CVSSv3, and CVSSv4 metrics arrays, which could be a Secondary > source with a lower score instead of the Primary source with the > actual severity score. > > This fix takes maximum CVSS score. > Hello, Does this patch interact with the open bug 15931 – CVE Reporting wrong CVSSv3 score (https://bugzilla.yoctoproject.org/show_bug.cgi?id=15931) ? Also, does this need to be fixed on master and/or whinlatter? If yes, you should first send this patch (adapted most likely) to master. Then, once merged, send a backport request to the stable branches. Thanks! > > Signed-off-by: Het Patel <hetpat@cisco.com> > --- > .../meta/cve-update-nvd2-native.bb | 55 +++++++++++++------ > 1 file changed, 39 insertions(+), 16 deletions(-) > > diff --git a/meta/recipes-core/meta/cve-update-nvd2-native.bb > b/meta/recipes-core/meta/cve-update-nvd2-native.bb > index 945bd1d927..28d5810d5d 100644 > --- a/meta/recipes-core/meta/cve-update-nvd2-native.bb > +++ b/meta/recipes-core/meta/cve-update-nvd2-native.bb > @@ -352,32 +352,55 @@ def update_db(conn, elt): > if desc['lang'] == 'en': > cveDesc = desc['value'] > date = elt['cve']['lastModified'] > + > + # Extract maximum CVSS scores from all sources (Primary and Secondary) > + cvssv2 = 0.0 > try: > - accessVector = > elt['cve']['metrics']['cvssMetricV2'][0]['cvssData']['accessVector'] > - vectorString = > elt['cve']['metrics']['cvssMetricV2'][0]['cvssData']['vectorString'] > - cvssv2 = > elt['cve']['metrics']['cvssMetricV2'][0]['cvssData']['baseScore'] > + # Iterate through all cvssMetricV2 entries and find the maximum > score > + for metric in elt['cve']['metrics']['cvssMetricV2']: > + score = metric['cvssData']['baseScore'] > + if score > cvssv2: > + cvssv2 = score > + accessVector = metric['cvssData']['accessVector'] > + vectorString = metric['cvssData']['vectorString'] > except KeyError: > - cvssv2 = 0.0 > - cvssv3 = None > + pass > + > + cvssv3 = 0.0 > try: > - accessVector = accessVector or > elt['cve']['metrics']['cvssMetricV30'][0]['cvssData']['attackVector'] > - vectorString = vectorString or > elt['cve']['metrics']['cvssMetricV30'][0]['cvssData']['vectorString'] > - cvssv3 = > elt['cve']['metrics']['cvssMetricV30'][0]['cvssData']['baseScore'] > + # Iterate through all cvssMetricV30 entries and find the maximum > score > + for metric in elt['cve']['metrics']['cvssMetricV30']: > + score = metric['cvssData']['baseScore'] > + if score > cvssv3: > + cvssv3 = score > + accessVector = accessVector or > metric['cvssData']['attackVector'] > + vectorString = vectorString or > metric['cvssData']['vectorString'] > except KeyError: > pass > + > try: > - accessVector = accessVector or > elt['cve']['metrics']['cvssMetricV31'][0]['cvssData']['attackVector'] > - vectorString = vectorString or > elt['cve']['metrics']['cvssMetricV31'][0]['cvssData']['vectorString'] > - cvssv3 = cvssv3 or > elt['cve']['metrics']['cvssMetricV31'][0]['cvssData']['baseScore'] > + # Iterate through all cvssMetricV31 entries and find the maximum > score > + for metric in elt['cve']['metrics']['cvssMetricV31']: > + score = metric['cvssData']['baseScore'] > + if score > cvssv3: > + cvssv3 = score > + accessVector = accessVector or > metric['cvssData']['attackVector'] > + vectorString = vectorString or > metric['cvssData']['vectorString'] > except KeyError: > pass > - cvssv3 = cvssv3 or 0.0 > + > + cvssv4 = 0.0 > try: > - accessVector = accessVector or > elt['cve']['metrics']['cvssMetricV40'][0]['cvssData']['attackVector'] > - vectorString = vectorString or > elt['cve']['metrics']['cvssMetricV40'][0]['cvssData']['vectorString'] > - cvssv4 = > elt['cve']['metrics']['cvssMetricV40'][0]['cvssData']['baseScore'] > + # Iterate through all cvssMetricV40 entries and find the maximum > score > + for metric in elt['cve']['metrics']['cvssMetricV40']: > + score = metric['cvssData']['baseScore'] > + if score > cvssv4: > + cvssv4 = score > + accessVector = accessVector or > metric['cvssData']['attackVector'] > + vectorString = vectorString or > metric['cvssData']['vectorString'] > except KeyError: > - cvssv4 = 0.0 > + pass > + > accessVector = accessVector or "UNKNOWN" > vectorString = vectorString or "UNKNOWN" > > > -=-=-=-=-=-=-=-=-=-=-=- > Links: You receive all messages sent to this group. > View/Reply Online (#229229): > https://lists.openembedded.org/g/openembedded-core/message/229229 > Mute This Topic: https://lists.openembedded.org/mt/117239924/4316185 > Group Owner: openembedded-core+owner@lists.openembedded.org > Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [ > yoann.congal@smile.fr] > -=-=-=-=-=-=-=-=-=-=-=- > >
Hi, Yes, this patch directly addresses Bug 15931 (CVE Reporting wrong CVSSv3 score). The bug reports two issues: 1. The code only extracted the first element [0] from the CVSS metrics arrays, which could be a Secondary source with a lower score instead of the Primary source 2. The cvssv3 = cvssv3 or ... logic meant v3.0 scores took precedence over v3.1 scores This patch fixes both by iterating through all metric entries and selecting the maximum score. I will send this patch to the master first. Once merged, I'll submit a backport request to the stable branches. Thanks, Het
diff --git a/meta/recipes-core/meta/cve-update-nvd2-native.bb b/meta/recipes-core/meta/cve-update-nvd2-native.bb index 945bd1d927..28d5810d5d 100644 --- a/meta/recipes-core/meta/cve-update-nvd2-native.bb +++ b/meta/recipes-core/meta/cve-update-nvd2-native.bb @@ -352,32 +352,55 @@ def update_db(conn, elt): if desc['lang'] == 'en': cveDesc = desc['value'] date = elt['cve']['lastModified'] + + # Extract maximum CVSS scores from all sources (Primary and Secondary) + cvssv2 = 0.0 try: - accessVector = elt['cve']['metrics']['cvssMetricV2'][0]['cvssData']['accessVector'] - vectorString = elt['cve']['metrics']['cvssMetricV2'][0]['cvssData']['vectorString'] - cvssv2 = elt['cve']['metrics']['cvssMetricV2'][0]['cvssData']['baseScore'] + # Iterate through all cvssMetricV2 entries and find the maximum score + for metric in elt['cve']['metrics']['cvssMetricV2']: + score = metric['cvssData']['baseScore'] + if score > cvssv2: + cvssv2 = score + accessVector = metric['cvssData']['accessVector'] + vectorString = metric['cvssData']['vectorString'] except KeyError: - cvssv2 = 0.0 - cvssv3 = None + pass + + cvssv3 = 0.0 try: - accessVector = accessVector or elt['cve']['metrics']['cvssMetricV30'][0]['cvssData']['attackVector'] - vectorString = vectorString or elt['cve']['metrics']['cvssMetricV30'][0]['cvssData']['vectorString'] - cvssv3 = elt['cve']['metrics']['cvssMetricV30'][0]['cvssData']['baseScore'] + # Iterate through all cvssMetricV30 entries and find the maximum score + for metric in elt['cve']['metrics']['cvssMetricV30']: + score = metric['cvssData']['baseScore'] + if score > cvssv3: + cvssv3 = score + accessVector = accessVector or metric['cvssData']['attackVector'] + vectorString = vectorString or metric['cvssData']['vectorString'] except KeyError: pass + try: - accessVector = accessVector or elt['cve']['metrics']['cvssMetricV31'][0]['cvssData']['attackVector'] - vectorString = vectorString or elt['cve']['metrics']['cvssMetricV31'][0]['cvssData']['vectorString'] - cvssv3 = cvssv3 or elt['cve']['metrics']['cvssMetricV31'][0]['cvssData']['baseScore'] + # Iterate through all cvssMetricV31 entries and find the maximum score + for metric in elt['cve']['metrics']['cvssMetricV31']: + score = metric['cvssData']['baseScore'] + if score > cvssv3: + cvssv3 = score + accessVector = accessVector or metric['cvssData']['attackVector'] + vectorString = vectorString or metric['cvssData']['vectorString'] except KeyError: pass - cvssv3 = cvssv3 or 0.0 + + cvssv4 = 0.0 try: - accessVector = accessVector or elt['cve']['metrics']['cvssMetricV40'][0]['cvssData']['attackVector'] - vectorString = vectorString or elt['cve']['metrics']['cvssMetricV40'][0]['cvssData']['vectorString'] - cvssv4 = elt['cve']['metrics']['cvssMetricV40'][0]['cvssData']['baseScore'] + # Iterate through all cvssMetricV40 entries and find the maximum score + for metric in elt['cve']['metrics']['cvssMetricV40']: + score = metric['cvssData']['baseScore'] + if score > cvssv4: + cvssv4 = score + accessVector = accessVector or metric['cvssData']['attackVector'] + vectorString = vectorString or metric['cvssData']['vectorString'] except KeyError: - cvssv4 = 0.0 + pass + accessVector = accessVector or "UNKNOWN" vectorString = vectorString or "UNKNOWN"