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)
