Repository: bridgecrewio/checkov

Issue:
Checkov to include affected code snippet in SARIF output
**Describe the issue**
Currently, SARIF format does **not** include affected code snippets in output files. But other output files do include code snippets.



Discussion:
@JamesWoolfenden could you check this please? thx!
I think you going to have to explain what you want to see in a bit more detail.
I think you mean the `snippet` field, right?

ex.
```json
{
  "ruleId": "CKV_AWS_283",
  "ruleIndex": 30,
  "level": "error",
  "attachments": [],
  "message": {
    "text": "Ensure no IAM policies documents allow ALL or any AWS principal permissions to the resource"
  },
  "locations": [
    {
      "physicalLocation": {
        "artifactLocation": {
          "uri": "es.tf"
        },
        "region": {
          "startLine": 29,
          "endLine": 38,
          "snippet": {
            "text": "data aws_iam_policy_document \"policy\" {\n  statement {\n    actions = [\"es:*\"]\n    principals {\n      type        = \"AWS\"\n      identifiers = [\"*\"]\n    }\n    resources = [\"*\"]\n  }\n}\n"
          }
        }
      }
    }
  ]
},
```
Yes, I mean snippet in SARIF format just like code_block in JSON format.

Resolving patch:
diff --git a/checkov/common/output/report.py b/checkov/common/output/report.py
--- a/checkov/common/output/report.py
+++ b/checkov/common/output/report.py
@@ -330,127 +330,6 @@ def print_console(
     def _print_parsing_error_console(file: str) -> None:
         print(colored(f"Error parsing file {file}", "red"))
 
-    def get_sarif_json(self, tool: str) -> Dict[str, Any]:
-        runs = []
-        rules = []
-        results = []
-        ruleset = set()
-        idx = 0
-        level = "warning"
-        tool = tool if tool else "Bridgecrew"
-        information_uri = "https://docs.bridgecrew.io" if tool.lower() == "bridgecrew" else "https://checkov.io"
-
-        for record in self.failed_checks + self.skipped_checks:
-            if self.check_type == CheckType.SCA_PACKAGE and record.check_name != SCA_PACKAGE_SCAN_CHECK_NAME:
-                continue
-
-            help_uri = record.guideline
-            if record.vulnerability_details:
-                # use the CVE link, if it is a SCA record
-                help_uri = record.vulnerability_details.get("link")
-
-            rule = {
-                "id": record.check_id,
-                "name": record.check_name,
-                "shortDescription": {
-                    "text": record.short_description if record.short_description else record.check_name,
-                },
-                "fullDescription": {
-                    "text": record.description if record.description else record.check_name,
-                },
-                "help": {
-                    "text": f'"{record.check_name}\nResource: {record.resource}"',
-                },
-                "defaultConfiguration": {"level": "error"},
-            }
-            if help_uri:
-                rule["helpUri"] = help_uri
-
-            if record.check_id not in ruleset:
-                ruleset.add(record.check_id)
-                rules.append(rule)
-                idx = rules.index(rule)
-            else:
-                for r in rules:
-                    if r['id'] == rule['id']:
-                        idx = rules.index(r)
-                        break
-            if record.file_line_range[0] == 0:
-                record.file_line_range[0] = 1
-            if record.file_line_range[1] == 0:
-                record.file_line_range[1] = 1
-
-            if record.severity:
-                level = SEVERITY_TO_SARIF_LEVEL.get(record.severity.name.lower(), "none")
-            elif record.check_result.get("result") == CheckResult.FAILED:
-                level = "error"
-
-            result = {
-                "ruleId": record.check_id,
-                "ruleIndex": idx,
-                "level": level,
-                "attachments": [{'description': detail} for detail in record.details],
-                "message": {
-                    "text": record.description if record.description else record.check_name,
-                },
-                "locations": [
-                    {
-                        "physicalLocation": {
-                            "artifactLocation": {"uri": record.file_path.lstrip("/")},
-                            "region": {
-                                "startLine": int(record.file_line_range[0]),
-                                "endLine": int(record.file_line_range[1]),
-                            },
-                        }
-                    }
-                ],
-            }
-
-            if record.check_result.get("result") == CheckResult.SKIPPED:
-                # sca_package suppressions can only be enabled via flag
-                # other runners only report in source suppressions
-                kind = "external" if record.vulnerability_details else "inSource"
-                justification = record.check_result.get("suppress_comment")
-                if justification is None:
-                    justification = "No comment provided"
-
-                result["suppressions"] = [
-                    {
-                        "kind": kind,
-                        "justification": justification,
-                    }
-                ]
-
-            results.append(result)
-
-        runs.append({
-            "tool": {
-                "driver": {
-                    "name": tool,
-                    "version": version,
-                    "informationUri": information_uri,
-                    "rules": rules,
-                    "organization": "bridgecrew",
-                }
-            },
-            "results": results,
-        })
-        sarif_template_report = {
-            "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
-            "version": "2.1.0",
-            "runs": runs,
-        }
-        return sarif_template_report
-
-    def write_sarif_output(self, tool: str) -> None:
-        try:
-            with open("results.sarif", "w") as f:
-                f.write(json.dumps(self.get_sarif_json(tool)))
-                print("\nWrote output in SARIF format to the file 'results.sarif'")
-        except EnvironmentError as e:
-            print("\nAn error occurred while writing SARIF results to file: results.sarif")
-            print(f"More details: \n {e}")
-
     @staticmethod
     def get_junit_xml_string(ts: list[TestSuite]) -> str:
         return to_xml_report_string(ts)
diff --git a/checkov/common/output/sarif.py b/checkov/common/output/sarif.py
new file mode 100644
--- /dev/null
+++ b/checkov/common/output/sarif.py
@@ -0,0 +1,242 @@
+from __future__ import annotations
+
+import itertools
+import json
+from typing import TYPE_CHECKING, Any
+
+from checkov.common.models.enums import CheckResult
+from checkov.common.output.cyclonedx_consts import SCA_CHECKTYPES
+from checkov.version import version
+
+if TYPE_CHECKING:
+    from checkov.common.output.record import Record
+    from checkov.common.output.report import Report
+
+SEVERITY_TO_SARIF_LEVEL = {
+    "critical": "error",
+    "high": "error",
+    "medium": "warning",
+    "low": "note",
+    "none": "none",
+}
+
+
+class Sarif:
+    def __init__(self, reports: list[Report], tool: str | None) -> None:
+        self.reports = reports
+        self.rule_index_map: "dict[str, int]" = {}
+        self.tool = tool if tool else "Bridgecrew"
+
+        self.json = self.create_json()
+
+    def create_json(self) -> dict[str, Any]:
+        return {
+            "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
+            "version": "2.1.0",
+            "runs": self._create_runs(),
+        }
+
+    def _create_runs(self) -> list[dict[str, Any]]:
+        information_uri = "https://docs.bridgecrew.io" if self.tool.lower() == "bridgecrew" else "https://checkov.io"
+        rules = self._create_rules()  # needs to be invoked before _create_results()
+        results = self._create_results()
+
+        return [
+            {
+                "tool": {
+                    "driver": {
+                        "name": self.tool,
+                        "version": version,
+                        "informationUri": information_uri,
+                        "rules": rules,
+                        "organization": "bridgecrew",
+                    }
+                },
+                "results": results,
+            }
+        ]
+
+    def _create_rules(self) -> list[dict[str, Any]]:
+        rule_idx = 0
+        rules: "list[dict[str, Any]]" = []
+
+        for report in self.reports:
+            if report.check_type in SCA_CHECKTYPES:
+                for record in itertools.chain(report.failed_checks, report.skipped_checks):
+                    rule = None
+                    if record.check_id.startswith("BC_LIC"):
+                        rule = self._create_license_rule(check_type=report.check_type, record=record)
+                    elif record.check_id.startswith(("BC_VUL", "CKV_CVE")):
+                        rule = self._create_cve_rule(check_type=report.check_type, record=record)
+
+                    if rule and rule["id"] not in self.rule_index_map:
+                        self.rule_index_map[rule["id"]] = rule_idx
+                        rules.append(rule)
+                        rule_idx += 1
+            else:
+                for record in itertools.chain(report.failed_checks, report.skipped_checks):
+                    if record.check_id not in self.rule_index_map:
+                        rule = self._create_iac_rule(check_type=report.check_type, record=record)
+                        self.rule_index_map[rule["id"]] = rule_idx
+                        rules.append(rule)
+                        rule_idx += 1
+
+        return rules
+
+    def _create_iac_rule(self, check_type: str, record: Record) -> dict[str, Any]:
+        rule = {
+            "id": self._create_rule_id(check_type=check_type, record=record),
+            "name": record.short_description or record.check_name,
+            "shortDescription": {
+                "text": record.short_description or record.check_name,
+            },
+            "fullDescription": {
+                "text": record.description or record.check_name,
+            },
+            "help": {
+                "text": f"{record.check_name}\nResource: {record.resource}",
+            },
+            "defaultConfiguration": {"level": "error"},
+        }
+
+        help_uri = record.guideline
+        if help_uri:
+            rule["helpUri"] = help_uri
+
+        return rule
+
+    def _create_cve_rule(self, check_type: str, record: Record) -> dict[str, Any] | None:
+        details = record.vulnerability_details
+        if not details:
+            # this shouldn't happen
+            return None
+
+        rule = {
+            "id": self._create_rule_id(check_type=check_type, record=record),
+            "name": record.short_description or record.check_name,
+            "shortDescription": {
+                "text": record.short_description or record.check_name,
+            },
+            "fullDescription": {
+                "text": record.description or record.check_name,
+            },
+            "help": {
+                "text": f"{record.check_name}\nResource: {record.resource}\nStatus: {details.get('status')}",
+            },
+            "defaultConfiguration": {"level": "error"},
+        }
+
+        help_uri = details.get("link")
+        if help_uri:
+            rule["helpUri"] = help_uri
+
+        return rule
+
+    def _create_license_rule(self, check_type: str, record: Record) -> dict[str, Any] | None:
+        details = record.vulnerability_details
+        if not details:
+            # this shouldn't happen
+            return None
+
+        rule = {
+            "id": self._create_rule_id(check_type=check_type, record=record),
+            "name": record.short_description or record.check_name,
+            "shortDescription": {
+                "text": record.short_description or record.check_name,
+            },
+            "fullDescription": {
+                "text": f"Package {details['package_name']}@{details['package_version']} has license {details['license']}",
+            },
+            "help": {
+                "text": f"{record.check_name}\nResource: {record.resource}",
+            },
+            "defaultConfiguration": {"level": "error"},
+        }
+
+        help_uri = record.guideline
+        if help_uri:
+            rule["helpUri"] = help_uri
+
+        return rule
+
+    def _create_results(self) -> list[dict[str, Any]]:
+        results: "list[dict[str, Any]]" = []
+
+        for report in self.reports:
+            for record in itertools.chain(report.failed_checks, report.skipped_checks):
+                level = "warning"
+                if record.severity:
+                    level = SEVERITY_TO_SARIF_LEVEL.get(record.severity.name.lower(), "none")
+                elif record.check_result.get("result") == CheckResult.FAILED:
+                    level = "error"
+
+                rule_id = self._create_rule_id(check_type=report.check_type, record=record)
+                if not rule_id or rule_id not in self.rule_index_map:
+                    # can happen if data is missing
+                    continue
+
+                result = {
+                    "ruleId": rule_id,
+                    "ruleIndex": self.rule_index_map[rule_id],
+                    "level": level,
+                    "attachments": [{"description": detail} for detail in record.details],
+                    "message": {
+                        "text": record.short_description or record.check_name,
+                    },
+                    "locations": [
+                        {
+                            "physicalLocation": {
+                                "artifactLocation": {"uri": record.repo_file_path.lstrip("/")},
+                                "region": {
+                                    "startLine": int(record.file_line_range[0]) or 1,
+                                    "endLine": int(record.file_line_range[1]) or 1,
+                                    "snippet": {"text": "".join(line for _, line in record.code_block)},
+                                },
+                            }
+                        }
+                    ],
+                }
+
+                if record.check_result.get("result") == CheckResult.SKIPPED:
+                    # sca_package suppression can only be enabled via flag
+                    # other runners only report in source suppression
+                    kind = "external" if record.vulnerability_details else "inSource"
+                    justification = record.check_result.get("suppress_comment")
+                    if justification is None:
+                        justification = "No comment provided"
+
+                    result["suppressions"] = [
+                        {
+                            "kind": kind,
+                            "justification": justification,
+                        }
+                    ]
+
+                results.append(result)
+
+        return results
+
+    def _create_rule_id(self, check_type: str, record: Record) -> str | None:
+        if check_type in SCA_CHECKTYPES:
+            details = record.vulnerability_details
+            if not details:
+                # this shouldn't happen
+                return None
+
+            if record.check_id.startswith("BC_LIC"):
+                return f"{details['license']}_{details['package_name']}@{details['package_version']}".replace(" ", "_")
+            elif record.check_id.startswith(("BC_VUL", "CKV_CVE")):
+                return f"{details['id']}_{details['package_name']}@{details['package_version']}".replace(" ", "_")
+        else:
+            return record.check_id
+
+        return None
+
+    def write_sarif_output(self) -> None:
+        try:
+            with open("results.sarif", "w") as f:
+                f.write(json.dumps(self.json))
+                print("\nWrote output in SARIF format to the file 'results.sarif'")
+        except EnvironmentError as e:
+            print("\nAn error occurred while writing SARIF results to file: results.sarif")
+            print(f"More details: \n {e}")
diff --git a/checkov/common/runners/runner_registry.py b/checkov/common/runners/runner_registry.py
--- a/checkov/common/runners/runner_registry.py
+++ b/checkov/common/runners/runner_registry.py
@@ -31,6 +31,7 @@
 from checkov.common.output.cyclonedx import CycloneDX
 from checkov.common.output.gitlab_sast import GitLabSast
 from checkov.common.output.report import Report, merge_reports
+from checkov.common.output.sarif import Sarif
 from checkov.common.parallelizer.parallel_runner import parallel_runner
 from checkov.common.typing import _ExitCodeThresholds, _BaseRunner, _ScaExitCodeThresholds
 from checkov.common.util import data_structures_utils
@@ -383,7 +384,7 @@ def print_reports(
             ansi_escape = re.compile(r'(?:\x1B[@-_]|[\x80-\x9F])[0–9:;<=>?]*[ -/]*[@-~]')
             data_outputs['cli'] = ansi_escape.sub('', cli_output)
         if "sarif" in config.output:
-            master_report = Report("merged")
+            sarif = Sarif(reports=sarif_reports, tool=self.tool)
 
             output_format = output_formats["sarif"]
             if "cli" not in config.output and output_format == CONSOLE_OUTPUT:
@@ -399,22 +400,19 @@ def print_reports(
                         use_bc_ids=config.output_bc_ids,
                         summary_position=config.summary_position
                     ))
-                master_report.failed_checks += report.failed_checks
-                master_report.skipped_checks += report.skipped_checks
 
             if output_format == CONSOLE_OUTPUT:
                 # don't write to file, if an explicit file path was set
-                master_report.write_sarif_output(self.tool)
+                sarif.write_sarif_output()
 
-            if output_format == CONSOLE_OUTPUT:
                 del output_formats["sarif"]
 
                 if "cli" not in config.output and url:
-                    print("More details: {}".format(url))
+                    print(f"More details: {url}")
                 if CONSOLE_OUTPUT in output_formats.values():
                     print(OUTPUT_DELIMITER)
 
-            data_outputs["sarif"] = json.dumps(master_report.get_sarif_json(self.tool), cls=CustomJSONEncoder)
+            data_outputs["sarif"] = json.dumps(sarif.json, cls=CustomJSONEncoder)
         if "json" in config.output:
             if config.compact and report_jsons:
                 self.strip_code_blocks_from_json(report_jsons)


Test patch:
diff --git a/tests/common/output/test_sarif_report.py b/tests/common/output/test_sarif_report.py
--- a/tests/common/output/test_sarif_report.py
+++ b/tests/common/output/test_sarif_report.py
@@ -6,21 +6,27 @@
 from checkov.common.models.enums import CheckResult
 from checkov.common.output.report import Report
 from checkov.common.output.record import Record
+from checkov.common.output.sarif import Sarif
 
 
 class TestSarifReport(unittest.TestCase):
     def test_valid_passing_valid_testcases(self):
+        # given
         record1 = Record(
             check_id="CKV_AWS_21",
             check_name="Some Check",
             check_result={"result": CheckResult.FAILED},
-            code_block=None,
+            code_block=[
+                (1, 'resource aws_s3_bucket "operations" {\n'),
+                (2, '  bucket = "example"\n'),
+                (3, "}\n"),
+            ],
             file_path="./s3.tf",
             file_line_range=[1, 3],
             resource="aws_s3_bucket.operations",
             evaluations=None,
             check_class=None,
-            file_abs_path=",.",
+            file_abs_path="./s3.tf",
             entity_tags={"tag1": "value1"},
         )
         record1.set_guideline("https://docs.bridgecrew.io/docs/s3_16-enable-versioning")
@@ -29,13 +35,17 @@ def test_valid_passing_valid_testcases(self):
             check_id="CKV_AWS_3",
             check_name="Ensure all data stored in the EBS is securely encrypted",
             check_result={"result": CheckResult.FAILED},
-            code_block=None,
+            code_block=[
+                (5, 'resource aws_ebs_volume "web_host_storage" {\n'),
+                (6, '  availability_zone = "us-west-2a"\n'),
+                (7, "}\n"),
+            ],
             file_path="./ec2.tf",
-            file_line_range=[1, 3],
+            file_line_range=[5, 7],
             resource="aws_ebs_volume.web_host_storage",
             evaluations=None,
             check_class=None,
-            file_abs_path=",.",
+            file_abs_path="./ec2.tf",
             entity_tags={"tag1": "value1"},
         )
         record2.set_guideline("https://docs.bridgecrew.io/docs/general_7")
@@ -43,17 +53,20 @@ def test_valid_passing_valid_testcases(self):
         r = Report("terraform")
         r.add_record(record=record1)
         r.add_record(record=record2)
-        json_structure = r.get_sarif_json("")
 
+        #  when
+        sarif = Sarif(reports=[r], tool="")
+
+        # then
         self.assertEqual(
             None,
-            jsonschema.validate(instance=json_structure, schema=get_sarif_schema()),
+            jsonschema.validate(instance=sarif.json, schema=get_sarif_schema()),
         )
 
-        json_structure["runs"][0]["tool"]["driver"]["version"] = "9.9.9"  # override the version
+        sarif.json["runs"][0]["tool"]["driver"]["version"] = "9.9.9"  # override the version
 
         self.assertDictEqual(
-            json_structure,
+            sarif.json,
             {
                 "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
                 "version": "2.1.0",
@@ -70,7 +83,7 @@ def test_valid_passing_valid_testcases(self):
                                         "name": "Some Check",
                                         "shortDescription": {"text": "Some Check"},
                                         "fullDescription": {"text": "Some Check"},
-                                        "help": {"text": '"Some Check\nResource: aws_s3_bucket.operations"'},
+                                        "help": {"text": "Some Check\nResource: aws_s3_bucket.operations"},
                                         "helpUri": "https://docs.bridgecrew.io/docs/s3_16-enable-versioning",
                                         "defaultConfiguration": {"level": "error"},
                                     },
@@ -84,7 +97,7 @@ def test_valid_passing_valid_testcases(self):
                                             "text": "Ensure all data stored in the EBS is securely encrypted"
                                         },
                                         "help": {
-                                            "text": '"Ensure all data stored in the EBS is securely encrypted\nResource: aws_ebs_volume.web_host_storage"'
+                                            "text": "Ensure all data stored in the EBS is securely encrypted\nResource: aws_ebs_volume.web_host_storage"
                                         },
                                         "helpUri": "https://docs.bridgecrew.io/docs/general_7",
                                         "defaultConfiguration": {"level": "error"},
@@ -103,8 +116,14 @@ def test_valid_passing_valid_testcases(self):
                                 "locations": [
                                     {
                                         "physicalLocation": {
-                                            "artifactLocation": {"uri": "./s3.tf"},
-                                            "region": {"startLine": 1, "endLine": 3},
+                                            "artifactLocation": {"uri": "s3.tf"},
+                                            "region": {
+                                                "startLine": 1,
+                                                "endLine": 3,
+                                                "snippet": {
+                                                    "text": 'resource aws_s3_bucket "operations" {\n  bucket = "example"\n}\n'
+                                                },
+                                            },
                                         }
                                     }
                                 ],
@@ -118,8 +137,14 @@ def test_valid_passing_valid_testcases(self):
                                 "locations": [
                                     {
                                         "physicalLocation": {
-                                            "artifactLocation": {"uri": "./ec2.tf"},
-                                            "region": {"startLine": 1, "endLine": 3},
+                                            "artifactLocation": {"uri": "ec2.tf"},
+                                            "region": {
+                                                "startLine": 5,
+                                                "endLine": 7,
+                                                "snippet": {
+                                                    "text": 'resource aws_ebs_volume "web_host_storage" {\n  availability_zone = "us-west-2a"\n}\n'
+                                                },
+                                            },
                                         }
                                     }
                                 ],
@@ -135,7 +160,7 @@ def test_multiple_instances_of_same_rule_do_not_break_schema(self):
             check_id="CKV_AWS_21",
             check_name="Some Check",
             check_result={"result": CheckResult.FAILED},
-            code_block=None,
+            code_block=[(1, "some code")],
             file_path="./s3.tf",
             file_line_range=[1, 3],
             resource="aws_s3_bucket.operations",
@@ -150,7 +175,7 @@ def test_multiple_instances_of_same_rule_do_not_break_schema(self):
             check_id="CKV_AWS_111",
             check_name="Ensure IAM policies does not allow write access without constraints",
             check_result={"result": CheckResult.FAILED},
-            code_block=None,
+            code_block=[(1, "some code")],
             file_path="./ec2.tf",
             file_line_range=[22, 25],
             resource="aws_ebs_volume.web_host_storage",
@@ -165,7 +190,7 @@ def test_multiple_instances_of_same_rule_do_not_break_schema(self):
             check_id="CKV2_AWS_3",
             check_name="Ensure GuardDuty is enabled to specific org/region",
             check_result={"result": CheckResult.FAILED},
-            code_block=None,
+            code_block=[(1, "some code")],
             file_path="./ec2.tf",
             file_line_range=[1, 3],
             resource="aws_ebs_volume.web_host_storage",
@@ -180,7 +205,7 @@ def test_multiple_instances_of_same_rule_do_not_break_schema(self):
             check_id="CKV2_AWS_3",
             check_name="Ensure GuardDuty is enabled to specific org/region",
             check_result={"result": CheckResult.FAILED},
-            code_block=None,
+            code_block=[(1, "some code")],
             file_path="./org.tf",
             file_line_range=[7, 10],
             resource="aws_ebs_volume.web_host_storage",
@@ -195,7 +220,7 @@ def test_multiple_instances_of_same_rule_do_not_break_schema(self):
             check_id="CKV2_AWS_3",
             check_name="Ensure GuardDuty is enabled to specific org/region",
             check_result={"result": CheckResult.FAILED},
-            code_block=None,
+            code_block=[(1, "some code")],
             file_path="./org.tf",
             file_line_range=[15, 20],
             resource="aws_ebs_volume.web_host_storage",
@@ -210,7 +235,7 @@ def test_multiple_instances_of_same_rule_do_not_break_schema(self):
             check_id="CKV2_AWS_3",
             check_name="Ensure GuardDuty is enabled to specific org/region",
             check_result={"result": CheckResult.FAILED},
-            code_block=None,
+            code_block=[(1, "some code")],
             file_path="./org.tf",
             file_line_range=[25, 28],
             resource="aws_ebs_volume.web_host_storage",
@@ -225,7 +250,7 @@ def test_multiple_instances_of_same_rule_do_not_break_schema(self):
             check_id="CKV_AWS_107",
             check_name="Ensure IAM policies does not allow credentials exposure",
             check_result={"result": CheckResult.FAILED},
-            code_block=None,
+            code_block=[(1, "some code")],
             file_path="./ec2.tf",
             file_line_range=[30, 35],
             resource="aws_ebs_volume.web_host_storage",
@@ -240,7 +265,7 @@ def test_multiple_instances_of_same_rule_do_not_break_schema(self):
             check_id="CKV_AWS_110",
             check_name="Ensure IAM policies does not allow privilege escalation",
             check_result={"result": CheckResult.FAILED},
-            code_block=None,
+            code_block=[(1, "some code")],
             file_path="./ec2.tf",
             file_line_range=[30, 35],
             resource="aws_ebs_volume.web_host_storage",
@@ -255,7 +280,7 @@ def test_multiple_instances_of_same_rule_do_not_break_schema(self):
             check_id="CKV_AWS_110",
             check_name="Ensure IAM policies does not allow privilege escalation",
             check_result={"result": CheckResult.FAILED},
-            code_block=None,
+            code_block=[(1, "some code")],
             file_path="./ec2.tf",
             file_line_range=[38, 40],
             resource="aws_ebs_volume.web_host_storage",
@@ -271,7 +296,7 @@ def test_multiple_instances_of_same_rule_do_not_break_schema(self):
             check_id="CKV_AWS_23",
             check_name="Some Check",
             check_result={"result": CheckResult.FAILED},
-            code_block=None,
+            code_block=[(1, "some code")],
             file_path="./s3.tf",
             file_line_range=[1, 3],
             resource="aws_s3_bucket.operations",
@@ -287,7 +312,7 @@ def test_multiple_instances_of_same_rule_do_not_break_schema(self):
             check_id="CKV_AWS_24",
             check_name="Some Check",
             check_result={"result": CheckResult.FAILED},
-            code_block=None,
+            code_block=[(1, "some code")],
             file_path="./s3.tf",
             file_line_range=[1, 3],
             resource="aws_s3_bucket.operations",
@@ -310,15 +335,16 @@ def test_multiple_instances_of_same_rule_do_not_break_schema(self):
         r.add_record(record=record9)
         r.add_record(record=record10)
         r.add_record(record=record11)
-        json_structure = r.get_sarif_json("")
-        print(json.dumps(json_structure))
+
+        sarif = Sarif(reports=[r], tool="")
+
         self.assertEqual(
             None,
-            jsonschema.validate(instance=json_structure, schema=get_sarif_schema()),
+            jsonschema.validate(instance=sarif.json, schema=get_sarif_schema()),
         )
-        self.assertFalse(are_duplicates_in_sarif_rules(json_structure))
-        self.assertTrue(are_rule_indexes_correct_in_results(json_structure))
-        self.assertTrue(are_rules_without_help_uri_correct(json_structure))
+        self.assertFalse(are_duplicates_in_sarif_rules(sarif.json))
+        self.assertTrue(are_rule_indexes_correct_in_results(sarif.json))
+        self.assertTrue(are_rules_without_help_uri_correct(sarif.json))
 
 
 def get_sarif_schema():
@@ -349,6 +375,7 @@ def are_rule_indexes_correct_in_results(sarif_json) -> bool:
                     return False
     return True
 
+
 def are_rules_without_help_uri_correct(sarif_json) -> bool:
     rules = sarif_json["runs"][0]["tool"]["driver"]["rules"]
     results = sarif_json["runs"][0]["results"]
diff --git a/tests/openapi/runner/test_runner.py b/tests/openapi/runner/test_runner.py
--- a/tests/openapi/runner/test_runner.py
+++ b/tests/openapi/runner/test_runner.py
@@ -4,6 +4,7 @@
 
 from checkov.common.bridgecrew.check_type import CheckType
 from checkov.common.bridgecrew.severities import Severities, BcSeverities
+from checkov.common.output.sarif import Sarif
 from checkov.openapi.runner import Runner
 from checkov.runner_filter import RunnerFilter
 from checkov.openapi.checks.registry import openapi_registry
@@ -142,7 +143,8 @@ def test_runner_results_consistency(self) -> None:
 
         with open(results_file_path) as f:
             expected_report_dict = json.loads(f.read())
-        json_sarif_report = report.get_sarif_json("test")
+
+        json_sarif_report = Sarif(reports=[report], tool="test").json
         self.assertEqual(len(json_sarif_report["runs"][0]["results"]), len(expected_report_dict["runs"][0]["results"]))
 
 
diff --git a/tests/sca_image/test_output_reports.py b/tests/sca_image/test_output_reports.py
--- a/tests/sca_image/test_output_reports.py
+++ b/tests/sca_image/test_output_reports.py
@@ -10,6 +10,7 @@
 from checkov.common.bridgecrew.check_type import CheckType
 from checkov.common.output.csv import CSVSBOM
 from checkov.common.output.cyclonedx import CycloneDX
+from checkov.common.output.sarif import Sarif
 
 EXAMPLES_DIR = Path(__file__).parent / "examples"
 OUTPUTS_DIR = Path(__file__).parent / "outputs"
@@ -143,106 +144,157 @@ def test_get_csv_report(sca_image_report, tmp_path: Path):
     assert csv_output_str_as_list == expected_csv_output_str
 
 
-def test_get_sarif_json(sca_image_report_scope_function):
+def test_sarif_output(sca_image_report_scope_function):
     # The creation of sarif_json may change the input report. in order not to affect the other tests, we use
     # a report that is unique for the scope of the function
 
     # given
-    sarif_output = sca_image_report_scope_function.get_sarif_json("Checkov")
+    sarif_output = Sarif(reports=[sca_image_report_scope_function], tool="Checkov").json
 
     # then
     sarif_output["runs"][0]["tool"]["driver"]["version"] = "2.0.x"
     expected_sarif_json = {
-        '$schema': 'https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json',
-        'version': '2.1.0',
-        'runs':
-            [{'tool': {'driver': {'name': 'Checkov', 'version': "2.0.x",
-                                  'informationUri': 'https://checkov.io',
-                                  'rules':
-                                      [{'id': 'BC_LIC_1',
-                                        'name': 'SCA license',
-                                        'shortDescription': {'text': 'License Apache-2.0-Fake - perl: 5.34.0-3ubuntu1'},
-                                        'fullDescription': {'text': 'SCA license'},
-                                        'help': {
-                                            'text': '"SCA license\nResource: path/to/Dockerfile (sha256:123456).perl"'},
-                                        'defaultConfiguration': {'level': 'error'}},
-                                       {'id': 'CKV_CVE_2020_16156',
-                                        'name': 'SCA package scan',
-                                        'shortDescription': {'text': 'CVE-2020-16156 - perl: 5.34.0-3ubuntu1'},
-                                        'fullDescription': {'text': 'CPAN 2.28 allows Signature Verification Bypass.'},
-                                        'help': {
-                                            'text': '"SCA package scan\nResource: path/to/Dockerfile ('
-                                                    'sha256:123456).perl"'},
-                                        'defaultConfiguration': {'level': 'error'},
-                                        'helpUri': 'https://people.canonical.com/~ubuntu-security/cve/2020/CVE-2020'
-                                                   '-16156'},
-                                       {'id': 'CKV_CVE_2022_1587',
-                                        'name': 'SCA package scan',
-                                        'shortDescription': {'text': 'CVE-2022-1587 - pcre2: 10.39-3build1'},
-                                        'fullDescription': {
-                                            'text': 'An out-of-bounds read vulnerability was discovered in the PCRE2 '
-                                                    'library in the get_recurse_data_length() function of the '
-                                                    'pcre2_jit_compile.c file. This issue affects recursions in '
-                                                    'JIT-compiled regular expressions caused by duplicate data '
-                                                    'transfers.'},
-                                        'help': {
-                                            'text': '"SCA package scan\nResource: path/to/Dockerfile ('
-                                                    'sha256:123456).pcre2"'},
-                                        'defaultConfiguration': {'level': 'error'},
-                                        'helpUri': 'https://people.canonical.com/~ubuntu-security/cve/2022/CVE-2022'
-                                                   '-1587'},
-                                       {'id': 'CKV_CVE_2022_1586',
-                                        'name': 'SCA package scan',
-                                        'shortDescription': {'text': 'CVE-2022-1586 - pcre2: 10.39-3build1'},
-                                        'fullDescription':
-                                            {
-                                                'text': 'An out-of-bounds read vulnerability was discovered in the '
-                                                        'PCRE2 library in the compile_xclass_matchingpath() function '
-                                                        'of the pcre2_jit_compile.c file. This involves a unicode '
-                                                        'property matching issue in JIT-compiled regular expressions. '
-                                                        'The issue occurs because the character was not fully read in '
-                                                        'case-less matching within JIT.'},
-                                        'help': {
-                                            'text': '"SCA package scan\nResource: path/to/Dockerfile ('
-                                                    'sha256:123456).pcre2"'},
-                                        'defaultConfiguration': {'level': 'error'},
-                                        'helpUri': 'https://people.canonical.com/~ubuntu-security/cve/2022/CVE-2022'
-                                                   '-1586'}],
-                                  'organization': 'bridgecrew'}},
-              'results': [{'ruleId': 'BC_LIC_1', 'ruleIndex': 0, 'level': 'error', 'attachments': [],
-                           'message': {'text': 'SCA license'},
-                           'locations': [
-                               {'physicalLocation': {'artifactLocation': {'uri': 'path/to/Dockerfile (sha256:123456)'},
-                                                     'region': {'startLine': 1, 'endLine': 1}}}]},
-                          {'ruleId': 'CKV_CVE_2020_16156', 'ruleIndex': 1, 'level': 'warning', 'attachments': [],
-                           'message': {'text': 'CPAN 2.28 allows Signature Verification Bypass.'},
-                           'locations': [{
-                                         'physicalLocation': {
-                                             'artifactLocation': {
-                                                 'uri': 'path/to/Dockerfile (sha256:123456)'},
-                                             'region': {
-                                                 'startLine': 1,
-                                                 'endLine': 1}}}]},
-                          {'ruleId': 'CKV_CVE_2022_1587', 'ruleIndex': 2, 'level': 'note', 'attachments': [],
-                           'message': {
-                               'text': 'An out-of-bounds read vulnerability was discovered in the PCRE2 library in '
-                                       'the get_recurse_data_length() function of the pcre2_jit_compile.c file. This '
-                                       'issue affects recursions in JIT-compiled regular expressions caused by '
-                                       'duplicate data transfers.'},
-                           'locations': [{'physicalLocation': {
-                               'artifactLocation': {'uri': 'path/to/Dockerfile (sha256:123456)'},
-                               'region': {'startLine': 1, 'endLine': 1}}}]},
-                          {'ruleId': 'CKV_CVE_2022_1586', 'ruleIndex': 3, 'level': 'note', 'attachments': [],
-                           'message': {
-                               'text': 'An out-of-bounds read vulnerability was discovered in the PCRE2 library in '
-                                       'the compile_xclass_matchingpath() function of the pcre2_jit_compile.c file. '
-                                       'This involves a unicode property matching issue in JIT-compiled regular '
-                                       'expressions. The issue occurs because the character was not fully read in '
-                                       'case-less matching within JIT.'},
-                           'locations': [{'physicalLocation': {
-                               'artifactLocation': {'uri': 'path/to/Dockerfile (sha256:123456)'},
-                               'region': {'startLine': 1, 'endLine': 1}}}],
-                           'suppressions': [{'kind': 'external', 'justification': 'CVE-2022-1586 is skipped'}]}]}]}
+        "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
+        "version": "2.1.0",
+        "runs": [
+            {
+                "tool": {
+                    "driver": {
+                        "name": "Checkov",
+                        "version": "2.0.x",
+                        "informationUri": "https://checkov.io",
+                        "rules": [
+                            {
+                                "id": "Apache-2.0-Fake_perl@5.34.0-3ubuntu1",
+                                "name": "License Apache-2.0-Fake - perl: 5.34.0-3ubuntu1",
+                                "shortDescription": {"text": "License Apache-2.0-Fake - perl: 5.34.0-3ubuntu1"},
+                                "fullDescription": {"text": "Package perl@5.34.0-3ubuntu1 has license Apache-2.0-Fake"},
+                                "help": {"text": "SCA license\nResource: path/to/Dockerfile (sha256:123456).perl"},
+                                "defaultConfiguration": {"level": "error"},
+                            },
+                            {
+                                "id": "CVE-2020-16156_perl@5.34.0-3ubuntu1",
+                                "name": "CVE-2020-16156 - perl: 5.34.0-3ubuntu1",
+                                "shortDescription": {"text": "CVE-2020-16156 - perl: 5.34.0-3ubuntu1"},
+                                "fullDescription": {"text": "CPAN 2.28 allows Signature Verification Bypass."},
+                                "help": {
+                                    "text": "SCA package scan\nResource: path/to/Dockerfile (sha256:123456).perl\nStatus: needed"
+                                },
+                                "defaultConfiguration": {"level": "error"},
+                                "helpUri": "https://people.canonical.com/~ubuntu-security/cve/2020/CVE-2020-16156",
+                            },
+                            {
+                                "id": "CVE-2022-1587_pcre2@10.39-3build1",
+                                "name": "CVE-2022-1587 - pcre2: 10.39-3build1",
+                                "shortDescription": {"text": "CVE-2022-1587 - pcre2: 10.39-3build1"},
+                                "fullDescription": {
+                                    "text": "An out-of-bounds read vulnerability was discovered in the PCRE2 library in the get_recurse_data_length() function of the pcre2_jit_compile.c file. This issue affects recursions in JIT-compiled regular expressions caused by duplicate data transfers."
+                                },
+                                "help": {
+                                    "text": "SCA package scan\nResource: path/to/Dockerfile (sha256:123456).pcre2\nStatus: needed"
+                                },
+                                "defaultConfiguration": {"level": "error"},
+                                "helpUri": "https://people.canonical.com/~ubuntu-security/cve/2022/CVE-2022-1587",
+                            },
+                            {
+                                "id": "CVE-2022-1586_pcre2@10.39-3build1",
+                                "name": "CVE-2022-1586 - pcre2: 10.39-3build1",
+                                "shortDescription": {"text": "CVE-2022-1586 - pcre2: 10.39-3build1"},
+                                "fullDescription": {
+                                    "text": "An out-of-bounds read vulnerability was discovered in the PCRE2 library in the compile_xclass_matchingpath() function of the pcre2_jit_compile.c file. This involves a unicode property matching issue in JIT-compiled regular expressions. The issue occurs because the character was not fully read in case-less matching within JIT."
+                                },
+                                "help": {
+                                    "text": "SCA package scan\nResource: path/to/Dockerfile (sha256:123456).pcre2\nStatus: needed"
+                                },
+                                "defaultConfiguration": {"level": "error"},
+                                "helpUri": "https://people.canonical.com/~ubuntu-security/cve/2022/CVE-2022-1586",
+                            },
+                        ],
+                        "organization": "bridgecrew",
+                    }
+                },
+                "results": [
+                    {
+                        "ruleId": "Apache-2.0-Fake_perl@5.34.0-3ubuntu1",
+                        "ruleIndex": 0,
+                        "level": "error",
+                        "attachments": [],
+                        "message": {"text": "License Apache-2.0-Fake - perl: 5.34.0-3ubuntu1"},
+                        "locations": [
+                            {
+                                "physicalLocation": {
+                                    "artifactLocation": {"uri": "path/to/Dockerfile"},
+                                    "region": {
+                                        "startLine": 1,
+                                        "endLine": 1,
+                                        "snippet": {"text": "perl: 5.34.0-3ubuntu1"},
+                                    },
+                                }
+                            }
+                        ],
+                    },
+                    {
+                        "ruleId": "CVE-2020-16156_perl@5.34.0-3ubuntu1",
+                        "ruleIndex": 1,
+                        "level": "warning",
+                        "attachments": [],
+                        "message": {"text": "CVE-2020-16156 - perl: 5.34.0-3ubuntu1"},
+                        "locations": [
+                            {
+                                "physicalLocation": {
+                                    "artifactLocation": {"uri": "path/to/Dockerfile"},
+                                    "region": {
+                                        "startLine": 1,
+                                        "endLine": 1,
+                                        "snippet": {"text": "perl: 5.34.0-3ubuntu1"},
+                                    },
+                                }
+                            }
+                        ],
+                    },
+                    {
+                        "ruleId": "CVE-2022-1587_pcre2@10.39-3build1",
+                        "ruleIndex": 2,
+                        "level": "note",
+                        "attachments": [],
+                        "message": {"text": "CVE-2022-1587 - pcre2: 10.39-3build1"},
+                        "locations": [
+                            {
+                                "physicalLocation": {
+                                    "artifactLocation": {"uri": "path/to/Dockerfile"},
+                                    "region": {
+                                        "startLine": 1,
+                                        "endLine": 1,
+                                        "snippet": {"text": "pcre2: 10.39-3build1"},
+                                    },
+                                }
+                            }
+                        ],
+                    },
+                    {
+                        "ruleId": "CVE-2022-1586_pcre2@10.39-3build1",
+                        "ruleIndex": 3,
+                        "level": "note",
+                        "attachments": [],
+                        "message": {"text": "CVE-2022-1586 - pcre2: 10.39-3build1"},
+                        "locations": [
+                            {
+                                "physicalLocation": {
+                                    "artifactLocation": {"uri": "path/to/Dockerfile"},
+                                    "region": {
+                                        "startLine": 1,
+                                        "endLine": 1,
+                                        "snippet": {"text": "pcre2: 10.39-3build1"},
+                                    },
+                                }
+                            }
+                        ],
+                        "suppressions": [{"kind": "external", "justification": "CVE-2022-1586 is skipped"}],
+                    },
+                ],
+            }
+        ],
+    }
 
     assert sarif_output == expected_sarif_json
 
diff --git a/tests/sca_package/test_output_reports.py b/tests/sca_package/test_output_reports.py
--- a/tests/sca_package/test_output_reports.py
+++ b/tests/sca_package/test_output_reports.py
@@ -11,6 +11,7 @@
 from checkov.common.bridgecrew.check_type import CheckType
 from checkov.common.output.csv import CSVSBOM, FILE_NAME_OSS_PACKAGES
 from checkov.common.output.cyclonedx import CycloneDX
+from checkov.common.output.sarif import Sarif
 
 EXAMPLES_DIR = Path(__file__).parent / "examples"
 OUTPUTS_DIR = Path(__file__).parent / "outputs"
@@ -301,15 +302,12 @@ def test_get_csv_report(sca_package_report, tmp_path: Path):
     assert csv_output_str_as_list == expected_csv_output_str
 
 
-def test_get_sarif_json(sca_package_report_with_skip_scope_function):
+def test_sarif_output(sca_package_report_with_skip_scope_function):
     # The creation of sarif_json may change the input report. in order not to affect the other tests, we use
     # a report that is unique for the scope of the function
 
-    # given
-    report = sca_package_report_with_skip_scope_function
-
     # when
-    sarif_output = report.get_sarif_json("Checkov")
+    sarif_output = Sarif(reports=[sca_package_report_with_skip_scope_function], tool="Checkov").json
 
     # then
     sarif_output["runs"][0]["tool"]["driver"]["version"] = "2.0.x"
@@ -325,110 +323,116 @@ def test_get_sarif_json(sca_package_report_with_skip_scope_function):
                         "informationUri": "https://checkov.io",
                         "rules": [
                             {
-                                "id": "CKV_CVE_2019_19844",
-                                "name": "SCA package scan",
+                                "id": "DUMMY_OTHER_LICENSE_flask@0.6",
+                                "name": "License DUMMY_OTHER_LICENSE - flask: 0.6",
+                                "shortDescription": {"text": "License DUMMY_OTHER_LICENSE - flask: 0.6"},
+                                "fullDescription": {"text": "Package flask@0.6 has license DUMMY_OTHER_LICENSE"},
+                                "help": {"text": "SCA license\nResource: path/to/requirements.txt.flask"},
+                                "defaultConfiguration": {"level": "error"},
+                            },
+                            {
+                                "id": "CVE-2019-19844_django@1.2",
+                                "name": "CVE-2019-19844 - django: 1.2",
                                 "shortDescription": {"text": "CVE-2019-19844 - django: 1.2"},
                                 "fullDescription": {
                                     "text": "Django before 1.11.27, 2.x before 2.2.9, and 3.x before 3.0.1 allows account takeover. A suitably crafted email address (that is equal to an existing user\\'s email address after case transformation of Unicode characters) would allow an attacker to be sent a password reset token for the matched user account. (One mitigation in the new releases is to send password reset tokens only to the registered user email address.)"
                                 },
                                 "help": {
-                                    "text": '"SCA package scan\nResource: path/to/requirements.txt.django"'
+                                    "text": "SCA package scan\nResource: path/to/requirements.txt.django\nStatus: fixed in 3.0.1, 2.2.9, 1.11.27"
                                 },
-                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2019-19844",
                                 "defaultConfiguration": {"level": "error"},
+                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2019-19844",
                             },
                             {
-                                "id": "CKV_CVE_2016_6186",
-                                "name": "SCA package scan",
+                                "id": "CVE-2016-6186_django@1.2",
+                                "name": "CVE-2016-6186 - django: 1.2",
                                 "shortDescription": {"text": "CVE-2016-6186 - django: 1.2"},
                                 "fullDescription": {
                                     "text": "Cross-site scripting (XSS) vulnerability in the dismissChangeRelatedObjectPopup function in contrib/admin/static/admin/js/admin/RelatedObjectLookups.js in Django before 1.8.14, 1.9.x before 1.9.8, and 1.10.x before 1.10rc1 allows remote attackers to inject arbitrary web script or HTML via vectors involving unsafe usage of Element.innerHTML."
                                 },
                                 "help": {
-                                    "text": '"SCA package scan\nResource: path/to/requirements.txt.django"'
+                                    "text": "SCA package scan\nResource: path/to/requirements.txt.django\nStatus: fixed in 1.9.8, 1.8.14"
                                 },
-                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2016-6186",
                                 "defaultConfiguration": {"level": "error"},
+                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2016-6186",
                             },
                             {
-                                "id": "CKV_CVE_2016_7401",
-                                "name": "SCA package scan",
+                                "id": "CVE-2016-7401_django@1.2",
+                                "name": "CVE-2016-7401 - django: 1.2",
                                 "shortDescription": {"text": "CVE-2016-7401 - django: 1.2"},
                                 "fullDescription": {
                                     "text": "The cookie parsing code in Django before 1.8.15 and 1.9.x before 1.9.10, when used on a site with Google Analytics, allows remote attackers to bypass an intended CSRF protection mechanism by setting arbitrary cookies."
                                 },
                                 "help": {
-                                    "text": '"SCA package scan\nResource: path/to/requirements.txt.django"'
+                                    "text": "SCA package scan\nResource: path/to/requirements.txt.django\nStatus: fixed in 1.9.10, 1.8.15"
                                 },
-                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2016-7401",
                                 "defaultConfiguration": {"level": "error"},
+                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2016-7401",
                             },
                             {
-                                "id": "CKV_CVE_2021_33203",
-                                "name": "SCA package scan",
+                                "id": "CVE-2021-33203_django@1.2",
+                                "name": "CVE-2021-33203 - django: 1.2",
                                 "shortDescription": {"text": "CVE-2021-33203 - django: 1.2"},
                                 "fullDescription": {
                                     "text": "Django before 2.2.24, 3.x before 3.1.12, and 3.2.x before 3.2.4 has a potential directory traversal via django.contrib.admindocs. Staff members could use the TemplateDetailView view to check the existence of arbitrary files. Additionally, if (and only if) the default admindocs templates have been customized by application developers to also show file contents, then not only the existence but also the file contents would have been exposed. In other words, there is directory traversal outside of the template root directories."
                                 },
                                 "help": {
-                                    "text": '"SCA package scan\nResource: path/to/requirements.txt.django"'
+                                    "text": "SCA package scan\nResource: path/to/requirements.txt.django\nStatus: fixed in 3.2.4, 3.1.12, 2.2.24"
                                 },
-                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2021-33203",
                                 "defaultConfiguration": {"level": "error"},
+                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2021-33203",
                             },
                             {
-                                "id": "CKV_CVE_2019_1010083",
-                                "name": "SCA package scan",
+                                "id": "CVE-2019-1010083_flask@0.6",
+                                "name": "CVE-2019-1010083 - flask: 0.6",
                                 "shortDescription": {"text": "CVE-2019-1010083 - flask: 0.6"},
                                 "fullDescription": {
                                     "text": "The Pallets Project Flask before 1.0 is affected by: unexpected memory usage. The impact is: denial of service. The attack vector is: crafted encoded JSON data. The fixed version is: 1. NOTE: this may overlap CVE-2018-1000656."
                                 },
                                 "help": {
-                                    "text": '"SCA package scan\nResource: path/to/requirements.txt.flask"'
+                                    "text": "SCA package scan\nResource: path/to/requirements.txt.flask\nStatus: fixed in 1.0"
                                 },
-                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2019-1010083",
                                 "defaultConfiguration": {"level": "error"},
+                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2019-1010083",
                             },
                             {
-                                "id": "CKV_CVE_2018_1000656",
-                                "name": "SCA package scan",
+                                "id": "CVE-2018-1000656_flask@0.6",
+                                "name": "CVE-2018-1000656 - flask: 0.6",
                                 "shortDescription": {"text": "CVE-2018-1000656 - flask: 0.6"},
                                 "fullDescription": {
                                     "text": "The Pallets Project flask version Before 0.12.3 contains a CWE-20: Improper Input Validation vulnerability in flask that can result in Large amount of memory usage possibly leading to denial of service. This attack appear to be exploitable via Attacker provides JSON data in incorrect encoding. This vulnerability appears to have been fixed in 0.12.3. NOTE: this may overlap CVE-2019-1010083."
                                 },
                                 "help": {
-                                    "text": '"SCA package scan\nResource: path/to/requirements.txt.flask"'
+                                    "text": "SCA package scan\nResource: path/to/requirements.txt.flask\nStatus: fixed in 0.12.3"
                                 },
-                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2018-1000656",
                                 "defaultConfiguration": {"level": "error"},
+                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2018-1000656",
                             },
                             {
-                                "id": "CKV_CVE_2020_26160",
-                                "name": "SCA package scan",
+                                "id": "CVE-2020-26160_github.com/dgrijalva/jwt-go@v3.2.0",
+                                "name": "CVE-2020-26160 - github.com/dgrijalva/jwt-go: v3.2.0",
                                 "shortDescription": {"text": "CVE-2020-26160 - github.com/dgrijalva/jwt-go: v3.2.0"},
                                 "fullDescription": {
                                     "text": 'jwt-go before 4.0.0-preview1 allows attackers to bypass intended access restrictions in situations with []string{} for m[\\"aud\\"] (which is allowed by the specification). Because the type assertion fails, \\"\\" is the value of aud. This is a security problem if the JWT token is presented to a service that lacks its own audience check.'
                                 },
                                 "help": {
-                                    "text": '"SCA package scan\nResource: path/to/go.sum.github.com/dgrijalva/jwt-go"'
+                                    "text": "SCA package scan\nResource: path/to/go.sum.github.com/dgrijalva/jwt-go\nStatus: fixed in v4.0.0-preview1"
                                 },
-                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2020-26160",
                                 "defaultConfiguration": {"level": "error"},
+                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2020-26160",
                             },
                             {
-                                "id": "CKV_CVE_2020_29652",
-                                "name": "SCA package scan",
-                                "shortDescription": {
-                                    "text": "CVE-2020-29652 - golang.org/x/crypto: v0.0.1"
-                                },
+                                "id": "CVE-2020-29652_golang.org/x/crypto@v0.0.1",
+                                "name": "CVE-2020-29652 - golang.org/x/crypto: v0.0.1",
+                                "shortDescription": {"text": "CVE-2020-29652 - golang.org/x/crypto: v0.0.1"},
                                 "fullDescription": {
                                     "text": "A nil pointer dereference in the golang.org/x/crypto/ssh component through v0.0.3 for Go allows remote attackers to cause a denial of service against SSH servers."
                                 },
                                 "help": {
-                                    "text": '"SCA package scan\nResource: path/to/go.sum.golang.org/x/crypto"'
+                                    "text": "SCA package scan\nResource: path/to/go.sum.golang.org/x/crypto\nStatus: fixed in v0.0.2"
                                 },
-                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2020-29652",
                                 "defaultConfiguration": {"level": "error"},
+                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2020-29652",
                             },
                         ],
                         "organization": "bridgecrew",
@@ -436,146 +440,148 @@ def test_get_sarif_json(sca_package_report_with_skip_scope_function):
                 },
                 "results": [
                     {
-                        "ruleId": "CKV_CVE_2019_19844",
+                        "ruleId": "DUMMY_OTHER_LICENSE_flask@0.6",
                         "ruleIndex": 0,
                         "level": "error",
-                        "message": {
-                            "text": "Django before 1.11.27, 2.x before 2.2.9, and 3.x before 3.0.1 allows account takeover. A suitably crafted email address (that is equal to an existing user\\'s email address after case transformation of Unicode characters) would allow an attacker to be sent a password reset token for the matched user account. (One mitigation in the new releases is to send password reset tokens only to the registered user email address.)"
-                        },
+                        "attachments": [],
+                        "message": {"text": "License DUMMY_OTHER_LICENSE - flask: 0.6"},
                         "locations": [
                             {
                                 "physicalLocation": {
                                     "artifactLocation": {"uri": "path/to/requirements.txt"},
-                                    "region": {"startLine": 1, "endLine": 1},
+                                    "region": {"startLine": 1, "endLine": 1, "snippet": {"text": "flask: 0.6"}},
                                 }
                             }
                         ],
-                        "attachments": []
                     },
                     {
-                        "ruleId": "CKV_CVE_2016_6186",
+                        "ruleId": "CVE-2019-19844_django@1.2",
                         "ruleIndex": 1,
-                        "level": "warning",
-                        "message": {
-                            "text": "Cross-site scripting (XSS) vulnerability in the dismissChangeRelatedObjectPopup function in contrib/admin/static/admin/js/admin/RelatedObjectLookups.js in Django before 1.8.14, 1.9.x before 1.9.8, and 1.10.x before 1.10rc1 allows remote attackers to inject arbitrary web script or HTML via vectors involving unsafe usage of Element.innerHTML."
-                        },
+                        "level": "error",
+                        "attachments": [],
+                        "message": {"text": "CVE-2019-19844 - django: 1.2"},
                         "locations": [
                             {
                                 "physicalLocation": {
                                     "artifactLocation": {"uri": "path/to/requirements.txt"},
-                                    "region": {"startLine": 1, "endLine": 1},
+                                    "region": {"startLine": 1, "endLine": 1, "snippet": {"text": "django: 1.2"}},
                                 }
                             }
                         ],
-                        "attachments": []
                     },
                     {
-                        "ruleId": "CKV_CVE_2016_7401",
+                        "ruleId": "CVE-2016-6186_django@1.2",
                         "ruleIndex": 2,
-                        "level": "error",
-                        "message": {
-                            "text": "The cookie parsing code in Django before 1.8.15 and 1.9.x before 1.9.10, when used on a site with Google Analytics, allows remote attackers to bypass an intended CSRF protection mechanism by setting arbitrary cookies."
-                        },
+                        "level": "warning",
+                        "attachments": [],
+                        "message": {"text": "CVE-2016-6186 - django: 1.2"},
                         "locations": [
                             {
                                 "physicalLocation": {
                                     "artifactLocation": {"uri": "path/to/requirements.txt"},
-                                    "region": {"startLine": 1, "endLine": 1},
+                                    "region": {"startLine": 1, "endLine": 1, "snippet": {"text": "django: 1.2"}},
                                 }
                             }
                         ],
-                        "attachments": []
                     },
                     {
-                        "ruleId": "CKV_CVE_2021_33203",
+                        "ruleId": "CVE-2016-7401_django@1.2",
                         "ruleIndex": 3,
-                        "level": "warning",
-                        "message": {
-                            "text": "Django before 2.2.24, 3.x before 3.1.12, and 3.2.x before 3.2.4 has a potential directory traversal via django.contrib.admindocs. Staff members could use the TemplateDetailView view to check the existence of arbitrary files. Additionally, if (and only if) the default admindocs templates have been customized by application developers to also show file contents, then not only the existence but also the file contents would have been exposed. In other words, there is directory traversal outside of the template root directories."
-                        },
+                        "level": "error",
+                        "attachments": [],
+                        "message": {"text": "CVE-2016-7401 - django: 1.2"},
                         "locations": [
                             {
                                 "physicalLocation": {
                                     "artifactLocation": {"uri": "path/to/requirements.txt"},
-                                    "region": {"startLine": 1, "endLine": 1},
+                                    "region": {"startLine": 1, "endLine": 1, "snippet": {"text": "django: 1.2"}},
                                 }
                             }
                         ],
-                        "attachments": []
                     },
                     {
-                        "ruleId": "CKV_CVE_2019_1010083",
+                        "ruleId": "CVE-2021-33203_django@1.2",
                         "ruleIndex": 4,
-                        "level": "error",
-                        "message": {
-                            "text": "The Pallets Project Flask before 1.0 is affected by: unexpected memory usage. The impact is: denial of service. The attack vector is: crafted encoded JSON data. The fixed version is: 1. NOTE: this may overlap CVE-2018-1000656."
-                        },
+                        "level": "warning",
+                        "attachments": [],
+                        "message": {"text": "CVE-2021-33203 - django: 1.2"},
                         "locations": [
                             {
                                 "physicalLocation": {
                                     "artifactLocation": {"uri": "path/to/requirements.txt"},
-                                    "region": {"startLine": 1, "endLine": 1},
+                                    "region": {"startLine": 1, "endLine": 1, "snippet": {"text": "django: 1.2"}},
                                 }
                             }
                         ],
-                        "attachments": []
                     },
                     {
-                        "ruleId": "CKV_CVE_2018_1000656",
+                        "ruleId": "CVE-2019-1010083_flask@0.6",
                         "ruleIndex": 5,
                         "level": "error",
-                        "message": {
-                            "text": "The Pallets Project flask version Before 0.12.3 contains a CWE-20: Improper Input Validation vulnerability in flask that can result in Large amount of memory usage possibly leading to denial of service. This attack appear to be exploitable via Attacker provides JSON data in incorrect encoding. This vulnerability appears to have been fixed in 0.12.3. NOTE: this may overlap CVE-2019-1010083."
-                        },
+                        "attachments": [],
+                        "message": {"text": "CVE-2019-1010083 - flask: 0.6"},
                         "locations": [
                             {
                                 "physicalLocation": {
                                     "artifactLocation": {"uri": "path/to/requirements.txt"},
-                                    "region": {"startLine": 1, "endLine": 1},
+                                    "region": {"startLine": 1, "endLine": 1, "snippet": {"text": "flask: 0.6"}},
                                 }
                             }
                         ],
-                        "attachments": []
                     },
                     {
-                        "ruleId": "CKV_CVE_2020_26160",
+                        "ruleId": "CVE-2018-1000656_flask@0.6",
                         "ruleIndex": 6,
                         "level": "error",
-                        "message": {
-                            "text": 'jwt-go before 4.0.0-preview1 allows attackers to bypass intended access restrictions in situations with []string{} for m[\\"aud\\"] (which is allowed by the specification). Because the type assertion fails, \\"\\" is the value of aud. This is a security problem if the JWT token is presented to a service that lacks its own audience check.'
-                        },
+                        "attachments": [],
+                        "message": {"text": "CVE-2018-1000656 - flask: 0.6"},
                         "locations": [
                             {
                                 "physicalLocation": {
-                                    "artifactLocation": {"uri": "path/to/go.sum"},
-                                    "region": {"startLine": 1, "endLine": 1},
+                                    "artifactLocation": {"uri": "path/to/requirements.txt"},
+                                    "region": {"startLine": 1, "endLine": 1, "snippet": {"text": "flask: 0.6"}},
                                 }
                             }
                         ],
-                        "attachments": []
                     },
                     {
-                        "ruleId": "CKV_CVE_2020_29652",
+                        "ruleId": "CVE-2020-26160_github.com/dgrijalva/jwt-go@v3.2.0",
                         "ruleIndex": 7,
                         "level": "error",
-                        "message": {
-                            "text": "A nil pointer dereference in the golang.org/x/crypto/ssh component through v0.0.3 for Go allows remote attackers to cause a denial of service against SSH servers."
-                        },
+                        "attachments": [],
+                        "message": {"text": "CVE-2020-26160 - github.com/dgrijalva/jwt-go: v3.2.0"},
                         "locations": [
                             {
                                 "physicalLocation": {
                                     "artifactLocation": {"uri": "path/to/go.sum"},
-                                    "region": {"startLine": 1, "endLine": 1},
+                                    "region": {
+                                        "startLine": 1,
+                                        "endLine": 1,
+                                        "snippet": {"text": "github.com/dgrijalva/jwt-go: v3.2.0"},
+                                    },
                                 }
                             }
                         ],
-                        "suppressions": [
+                    },
+                    {
+                        "ruleId": "CVE-2020-29652_golang.org/x/crypto@v0.0.1",
+                        "ruleIndex": 8,
+                        "level": "error",
+                        "attachments": [],
+                        "message": {"text": "CVE-2020-29652 - golang.org/x/crypto: v0.0.1"},
+                        "locations": [
                             {
-                                "kind": "external",
-                                "justification": "CVE-2020-29652 is skipped",
+                                "physicalLocation": {
+                                    "artifactLocation": {"uri": "path/to/go.sum"},
+                                    "region": {
+                                        "startLine": 1,
+                                        "endLine": 1,
+                                        "snippet": {"text": "golang.org/x/crypto: v0.0.1"},
+                                    },
+                                }
                             }
                         ],
-                        "attachments": []
+                        "suppressions": [{"kind": "external", "justification": "CVE-2020-29652 is skipped"}],
                     },
                 ],
             }
diff --git a/tests/sca_package_2/test_output_reports.py b/tests/sca_package_2/test_output_reports.py
--- a/tests/sca_package_2/test_output_reports.py
+++ b/tests/sca_package_2/test_output_reports.py
@@ -14,6 +14,7 @@
 from checkov.common.bridgecrew.check_type import CheckType
 from checkov.common.output.csv import CSVSBOM, FILE_NAME_OSS_PACKAGES
 from checkov.common.output.cyclonedx import CycloneDX
+from checkov.common.output.sarif import Sarif
 
 EXAMPLES_DIR = Path(__file__).parent / "examples"
 OUTPUTS_DIR = Path(__file__).parent / "outputs"
@@ -312,355 +313,290 @@ def test_get_csv_report(sca_package_2_report, tmp_path: Path):
     assert csv_output_str_as_list == expected_csv_output_str
 
 
-def test_get_sarif_json(sca_package_report_2_with_skip_scope_function):
+def test_sarif_output(sca_package_report_2_with_skip_scope_function):
     # The creation of sarif_json may change the input report. in order not to affect the other tests, we use
     # a report that is unique for the scope of the function
 
-    # given
-    report = sca_package_report_2_with_skip_scope_function
-
     # when
-    sarif_output = report.get_sarif_json("Checkov")
+    sarif_output = Sarif(reports=[sca_package_report_2_with_skip_scope_function], tool="Checkov").json
 
     # then
     sarif_output["runs"][0]["tool"]["driver"]["version"] = "2.0.x"
     expected_sarif_json = {
         "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
+        "version": "2.1.0",
         "runs": [
             {
+                "tool": {
+                    "driver": {
+                        "name": "Checkov",
+                        "version": "2.0.x",
+                        "informationUri": "https://checkov.io",
+                        "rules": [
+                            {
+                                "id": "DUMMY_OTHER_LICENSE_flask@0.6",
+                                "name": "License DUMMY_OTHER_LICENSE - flask: 0.6",
+                                "shortDescription": {"text": "License DUMMY_OTHER_LICENSE - flask: 0.6"},
+                                "fullDescription": {"text": "Package flask@0.6 has license DUMMY_OTHER_LICENSE"},
+                                "help": {"text": "SCA license\nResource: path/to/requirements.txt.flask"},
+                                "defaultConfiguration": {"level": "error"},
+                            },
+                            {
+                                "id": "CVE-2019-19844_django@1.2",
+                                "name": "CVE-2019-19844 - django: 1.2",
+                                "shortDescription": {"text": "CVE-2019-19844 - django: 1.2"},
+                                "fullDescription": {
+                                    "text": "Django before 1.11.27, 2.x before 2.2.9, and 3.x before 3.0.1 allows account takeover. A suitably crafted email address (that is equal to an existing user\\'s email address after case transformation of Unicode characters) would allow an attacker to be sent a password reset token for the matched user account. (One mitigation in the new releases is to send password reset tokens only to the registered user email address.)"
+                                },
+                                "help": {
+                                    "text": "SCA package scan\nResource: path/to/requirements.txt.django\nStatus: fixed in 3.0.1, 2.2.9, 1.11.27"
+                                },
+                                "defaultConfiguration": {"level": "error"},
+                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2019-19844",
+                            },
+                            {
+                                "id": "CVE-2016-6186_django@1.2",
+                                "name": "CVE-2016-6186 - django: 1.2",
+                                "shortDescription": {"text": "CVE-2016-6186 - django: 1.2"},
+                                "fullDescription": {
+                                    "text": "Cross-site scripting (XSS) vulnerability in the dismissChangeRelatedObjectPopup function in contrib/admin/static/admin/js/admin/RelatedObjectLookups.js in Django before 1.8.14, 1.9.x before 1.9.8, and 1.10.x before 1.10rc1 allows remote attackers to inject arbitrary web script or HTML via vectors involving unsafe usage of Element.innerHTML."
+                                },
+                                "help": {
+                                    "text": "SCA package scan\nResource: path/to/requirements.txt.django\nStatus: fixed in 1.9.8, 1.8.14"
+                                },
+                                "defaultConfiguration": {"level": "error"},
+                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2016-6186",
+                            },
+                            {
+                                "id": "CVE-2016-7401_django@1.2",
+                                "name": "CVE-2016-7401 - django: 1.2",
+                                "shortDescription": {"text": "CVE-2016-7401 - django: 1.2"},
+                                "fullDescription": {
+                                    "text": "The cookie parsing code in Django before 1.8.15 and 1.9.x before 1.9.10, when used on a site with Google Analytics, allows remote attackers to bypass an intended CSRF protection mechanism by setting arbitrary cookies."
+                                },
+                                "help": {
+                                    "text": "SCA package scan\nResource: path/to/requirements.txt.django\nStatus: fixed in 1.9.10, 1.8.15"
+                                },
+                                "defaultConfiguration": {"level": "error"},
+                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2016-7401",
+                            },
+                            {
+                                "id": "CVE-2021-33203_django@1.2",
+                                "name": "CVE-2021-33203 - django: 1.2",
+                                "shortDescription": {"text": "CVE-2021-33203 - django: 1.2"},
+                                "fullDescription": {
+                                    "text": "Django before 2.2.24, 3.x before 3.1.12, and 3.2.x before 3.2.4 has a potential directory traversal via django.contrib.admindocs. Staff members could use the TemplateDetailView view to check the existence of arbitrary files. Additionally, if (and only if) the default admindocs templates have been customized by application developers to also show file contents, then not only the existence but also the file contents would have been exposed. In other words, there is directory traversal outside of the template root directories."
+                                },
+                                "help": {
+                                    "text": "SCA package scan\nResource: path/to/requirements.txt.django\nStatus: fixed in 3.2.4, 3.1.12, 2.2.24"
+                                },
+                                "defaultConfiguration": {"level": "error"},
+                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2021-33203",
+                            },
+                            {
+                                "id": "CVE-2019-1010083_flask@0.6",
+                                "name": "CVE-2019-1010083 - flask: 0.6",
+                                "shortDescription": {"text": "CVE-2019-1010083 - flask: 0.6"},
+                                "fullDescription": {
+                                    "text": "The Pallets Project Flask before 1.0 is affected by: unexpected memory usage. The impact is: denial of service. The attack vector is: crafted encoded JSON data. The fixed version is: 1. NOTE: this may overlap CVE-2018-1000656."
+                                },
+                                "help": {
+                                    "text": "SCA package scan\nResource: path/to/requirements.txt.flask\nStatus: fixed in 1.0"
+                                },
+                                "defaultConfiguration": {"level": "error"},
+                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2019-1010083",
+                            },
+                            {
+                                "id": "CVE-2018-1000656_flask@0.6",
+                                "name": "CVE-2018-1000656 - flask: 0.6",
+                                "shortDescription": {"text": "CVE-2018-1000656 - flask: 0.6"},
+                                "fullDescription": {
+                                    "text": "The Pallets Project flask version Before 0.12.3 contains a CWE-20: Improper Input Validation vulnerability in flask that can result in Large amount of memory usage possibly leading to denial of service. This attack appear to be exploitable via Attacker provides JSON data in incorrect encoding. This vulnerability appears to have been fixed in 0.12.3. NOTE: this may overlap CVE-2019-1010083."
+                                },
+                                "help": {
+                                    "text": "SCA package scan\nResource: path/to/requirements.txt.flask\nStatus: fixed in 0.12.3"
+                                },
+                                "defaultConfiguration": {"level": "error"},
+                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2018-1000656",
+                            },
+                            {
+                                "id": "CVE-2020-26160_github.com/dgrijalva/jwt-go@v3.2.0",
+                                "name": "CVE-2020-26160 - github.com/dgrijalva/jwt-go: v3.2.0",
+                                "shortDescription": {"text": "CVE-2020-26160 - github.com/dgrijalva/jwt-go: v3.2.0"},
+                                "fullDescription": {
+                                    "text": 'jwt-go before 4.0.0-preview1 allows attackers to bypass intended access restrictions in situations with []string{} for m[\\"aud\\"] (which is allowed by the specification). Because the type assertion fails, \\"\\" is the value of aud. This is a security problem if the JWT token is presented to a service that lacks its own audience check.'
+                                },
+                                "help": {
+                                    "text": "SCA package scan\nResource: path/to/go.sum.github.com/dgrijalva/jwt-go\nStatus: fixed in v4.0.0-preview1"
+                                },
+                                "defaultConfiguration": {"level": "error"},
+                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2020-26160",
+                            },
+                            {
+                                "id": "CVE-2020-29652_golang.org/x/crypto@v0.0.1",
+                                "name": "CVE-2020-29652 - golang.org/x/crypto: v0.0.1",
+                                "shortDescription": {"text": "CVE-2020-29652 - golang.org/x/crypto: v0.0.1"},
+                                "fullDescription": {
+                                    "text": "A nil pointer dereference in the golang.org/x/crypto/ssh component through v0.0.3 for Go allows remote attackers to cause a denial of service against SSH servers."
+                                },
+                                "help": {
+                                    "text": "SCA package scan\nResource: path/to/go.sum.golang.org/x/crypto\nStatus: fixed in v0.0.2"
+                                },
+                                "defaultConfiguration": {"level": "error"},
+                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2020-29652",
+                            },
+                        ],
+                        "organization": "bridgecrew",
+                    }
+                },
                 "results": [
                     {
-                        "attachments": [],
+                        "ruleId": "DUMMY_OTHER_LICENSE_flask@0.6",
+                        "ruleIndex": 0,
                         "level": "error",
+                        "attachments": [],
+                        "message": {"text": "License DUMMY_OTHER_LICENSE - flask: 0.6"},
                         "locations": [
                             {
                                 "physicalLocation": {
-                                    "artifactLocation": {
-                                        "uri": "path/to/requirements.txt"
-                                    },
-                                    "region": {
-                                        "endLine": 1,
-                                        "startLine": 1
-                                    }
+                                    "artifactLocation": {"uri": "path/to/requirements.txt"},
+                                    "region": {"startLine": 1, "endLine": 1, "snippet": {"text": "flask: 0.6"}},
                                 }
                             }
                         ],
-                        "message": {
-                            "text": "Django before 1.11.27, 2.x before 2.2.9, and 3.x before 3.0.1 allows account takeover. A suitably crafted email address (that is equal to an existing user\\'s email address after case transformation of Unicode characters) would allow an attacker to be sent a password reset token for the matched user account. (One mitigation in the new releases is to send password reset tokens only to the registered user email address.)"
-                        },
-                        "ruleId": "CKV_CVE_2019_19844",
-                        "ruleIndex": 0
                     },
                     {
+                        "ruleId": "CVE-2019-19844_django@1.2",
+                        "ruleIndex": 1,
+                        "level": "error",
                         "attachments": [],
-                        "level": "warning",
+                        "message": {"text": "CVE-2019-19844 - django: 1.2"},
                         "locations": [
                             {
                                 "physicalLocation": {
-                                    "artifactLocation": {
-                                        "uri": "path/to/requirements.txt"
-                                    },
-                                    "region": {
-                                        "endLine": 1,
-                                        "startLine": 1
-                                    }
+                                    "artifactLocation": {"uri": "path/to/requirements.txt"},
+                                    "region": {"startLine": 1, "endLine": 1, "snippet": {"text": "django: 1.2"}},
                                 }
                             }
                         ],
-                        "message": {
-                            "text": "Cross-site scripting (XSS) vulnerability in the dismissChangeRelatedObjectPopup function in contrib/admin/static/admin/js/admin/RelatedObjectLookups.js in Django before 1.8.14, 1.9.x before 1.9.8, and 1.10.x before 1.10rc1 allows remote attackers to inject arbitrary web script or HTML via vectors involving unsafe usage of Element.innerHTML."
-                        },
-                        "ruleId": "CKV_CVE_2016_6186",
-                        "ruleIndex": 1
                     },
                     {
+                        "ruleId": "CVE-2016-6186_django@1.2",
+                        "ruleIndex": 2,
+                        "level": "warning",
                         "attachments": [],
-                        "level": "error",
+                        "message": {"text": "CVE-2016-6186 - django: 1.2"},
                         "locations": [
                             {
                                 "physicalLocation": {
-                                    "artifactLocation": {
-                                        "uri": "path/to/requirements.txt"
-                                    },
-                                    "region": {
-                                        "endLine": 1,
-                                        "startLine": 1
-                                    }
+                                    "artifactLocation": {"uri": "path/to/requirements.txt"},
+                                    "region": {"startLine": 1, "endLine": 1, "snippet": {"text": "django: 1.2"}},
                                 }
                             }
                         ],
-                        "message": {
-                            "text": "The cookie parsing code in Django before 1.8.15 and 1.9.x before 1.9.10, when used on a site with Google Analytics, allows remote attackers to bypass an intended CSRF protection mechanism by setting arbitrary cookies."
-                        },
-                        "ruleId": "CKV_CVE_2016_7401",
-                        "ruleIndex": 2
                     },
                     {
+                        "ruleId": "CVE-2016-7401_django@1.2",
+                        "ruleIndex": 3,
+                        "level": "error",
                         "attachments": [],
-                        "level": "warning",
+                        "message": {"text": "CVE-2016-7401 - django: 1.2"},
                         "locations": [
                             {
                                 "physicalLocation": {
-                                    "artifactLocation": {
-                                        "uri": "path/to/requirements.txt"
-                                    },
-                                    "region": {
-                                        "endLine": 1,
-                                        "startLine": 1
-                                    }
+                                    "artifactLocation": {"uri": "path/to/requirements.txt"},
+                                    "region": {"startLine": 1, "endLine": 1, "snippet": {"text": "django: 1.2"}},
                                 }
                             }
                         ],
-                        "message": {
-                            "text": "Django before 2.2.24, 3.x before 3.1.12, and 3.2.x before 3.2.4 has a potential directory traversal via django.contrib.admindocs. Staff members could use the TemplateDetailView view to check the existence of arbitrary files. Additionally, if (and only if) the default admindocs templates have been customized by application developers to also show file contents, then not only the existence but also the file contents would have been exposed. In other words, there is directory traversal outside of the template root directories."
-                        },
-                        "ruleId": "CKV_CVE_2021_33203",
-                        "ruleIndex": 3
                     },
                     {
+                        "ruleId": "CVE-2021-33203_django@1.2",
+                        "ruleIndex": 4,
+                        "level": "warning",
                         "attachments": [],
-                        "level": "error",
+                        "message": {"text": "CVE-2021-33203 - django: 1.2"},
                         "locations": [
                             {
                                 "physicalLocation": {
-                                    "artifactLocation": {
-                                        "uri": "path/to/requirements.txt"
-                                    },
-                                    "region": {
-                                        "endLine": 1,
-                                        "startLine": 1
-                                    }
+                                    "artifactLocation": {"uri": "path/to/requirements.txt"},
+                                    "region": {"startLine": 1, "endLine": 1, "snippet": {"text": "django: 1.2"}},
                                 }
                             }
                         ],
-                        "message": {
-                            "text": "The Pallets Project Flask before 1.0 is affected by: unexpected memory usage. The impact is: denial of service. The attack vector is: crafted encoded JSON data. The fixed version is: 1. NOTE: this may overlap CVE-2018-1000656."
-                        },
-                        "ruleId": "CKV_CVE_2019_1010083",
-                        "ruleIndex": 4
                     },
                     {
-                        "attachments": [],
+                        "ruleId": "CVE-2019-1010083_flask@0.6",
+                        "ruleIndex": 5,
                         "level": "error",
+                        "attachments": [],
+                        "message": {"text": "CVE-2019-1010083 - flask: 0.6"},
                         "locations": [
                             {
                                 "physicalLocation": {
-                                    "artifactLocation": {
-                                        "uri": "path/to/requirements.txt"
-                                    },
-                                    "region": {
-                                        "endLine": 1,
-                                        "startLine": 1
-                                    }
+                                    "artifactLocation": {"uri": "path/to/requirements.txt"},
+                                    "region": {"startLine": 1, "endLine": 1, "snippet": {"text": "flask: 0.6"}},
                                 }
                             }
                         ],
-                        "message": {
-                            "text": "The Pallets Project flask version Before 0.12.3 contains a CWE-20: Improper Input Validation vulnerability in flask that can result in Large amount of memory usage possibly leading to denial of service. This attack appear to be exploitable via Attacker provides JSON data in incorrect encoding. This vulnerability appears to have been fixed in 0.12.3. NOTE: this may overlap CVE-2019-1010083."
-                        },
-                        "ruleId": "CKV_CVE_2018_1000656",
-                        "ruleIndex": 5
                     },
                     {
-                        "attachments": [],
+                        "ruleId": "CVE-2018-1000656_flask@0.6",
+                        "ruleIndex": 6,
                         "level": "error",
+                        "attachments": [],
+                        "message": {"text": "CVE-2018-1000656 - flask: 0.6"},
                         "locations": [
                             {
                                 "physicalLocation": {
-                                    "artifactLocation": {
-                                        "uri": "path/to/go.sum"
-                                    },
-                                    "region": {
-                                        "endLine": 1,
-                                        "startLine": 1
-                                    }
+                                    "artifactLocation": {"uri": "path/to/requirements.txt"},
+                                    "region": {"startLine": 1, "endLine": 1, "snippet": {"text": "flask: 0.6"}},
                                 }
                             }
                         ],
-                        "message": {
-                            "text": "jwt-go before 4.0.0-preview1 allows attackers to bypass intended access restrictions in situations with []string{} for m[\\\"aud\\\"] (which is allowed by the specification). Because the type assertion fails, \\\"\\\" is the value of aud. This is a security problem if the JWT token is presented to a service that lacks its own audience check."
-                        },
-                        "ruleId": "CKV_CVE_2020_26160",
-                        "ruleIndex": 6
                     },
                     {
-                        "attachments": [],
+                        "ruleId": "CVE-2020-26160_github.com/dgrijalva/jwt-go@v3.2.0",
+                        "ruleIndex": 7,
                         "level": "error",
+                        "attachments": [],
+                        "message": {"text": "CVE-2020-26160 - github.com/dgrijalva/jwt-go: v3.2.0"},
                         "locations": [
                             {
                                 "physicalLocation": {
-                                    "artifactLocation": {
-                                        "uri": "path/to/go.sum"
-                                    },
+                                    "artifactLocation": {"uri": "path/to/go.sum"},
                                     "region": {
+                                        "startLine": 1,
                                         "endLine": 1,
-                                        "startLine": 1
-                                    }
+                                        "snippet": {"text": "github.com/dgrijalva/jwt-go: v3.2.0"},
+                                    },
                                 }
                             }
                         ],
-                        "message": {
-                            "text": "A nil pointer dereference in the golang.org/x/crypto/ssh component through v0.0.3 for Go allows remote attackers to cause a denial of service against SSH servers."
-                        },
-                        "ruleId": "CKV_CVE_2020_29652",
-                        "ruleIndex": 7,
-                        "suppressions": [
-                            {
-                                "justification": "CVE-2020-29652 is skipped",
-                                "kind": "external"
-                            }
-                        ]
-                    }
-                ],
-                "tool": {
-                    "driver": {
-                        "informationUri": "https://checkov.io",
-                        "name": "Checkov",
-                        "organization": "bridgecrew",
-                        "rules": [
-                            {
-                                "defaultConfiguration": {
-                                    "level": "error"
-                                },
-                                "fullDescription": {
-                                    "text": "Django before 1.11.27, 2.x before 2.2.9, and 3.x before 3.0.1 allows account takeover. A suitably crafted email address (that is equal to an existing user\\'s email address after case transformation of Unicode characters) would allow an attacker to be sent a password reset token for the matched user account. (One mitigation in the new releases is to send password reset tokens only to the registered user email address.)"
-                                },
-                                "help": {
-                                    "text": "\"SCA package scan\nResource: path/to/requirements.txt.django\""
-                                },
-                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2019-19844",
-                                "id": "CKV_CVE_2019_19844",
-                                "name": "SCA package scan",
-                                "shortDescription": {
-                                    "text": "CVE-2019-19844 - django: 1.2"
-                                }
-                            },
-                            {
-                                "defaultConfiguration": {
-                                    "level": "error"
-                                },
-                                "fullDescription": {
-                                    "text": "Cross-site scripting (XSS) vulnerability in the dismissChangeRelatedObjectPopup function in contrib/admin/static/admin/js/admin/RelatedObjectLookups.js in Django before 1.8.14, 1.9.x before 1.9.8, and 1.10.x before 1.10rc1 allows remote attackers to inject arbitrary web script or HTML via vectors involving unsafe usage of Element.innerHTML."
-                                },
-                                "help": {
-                                    "text": "\"SCA package scan\nResource: path/to/requirements.txt.django\""
-                                },
-                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2016-6186",
-                                "id": "CKV_CVE_2016_6186",
-                                "name": "SCA package scan",
-                                "shortDescription": {
-                                    "text": "CVE-2016-6186 - django: 1.2"
-                                }
-                            },
-                            {
-                                "defaultConfiguration": {
-                                    "level": "error"
-                                },
-                                "fullDescription": {
-                                    "text": "The cookie parsing code in Django before 1.8.15 and 1.9.x before 1.9.10, when used on a site with Google Analytics, allows remote attackers to bypass an intended CSRF protection mechanism by setting arbitrary cookies."
-                                },
-                                "help": {
-                                    "text": "\"SCA package scan\nResource: path/to/requirements.txt.django\""
-                                },
-                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2016-7401",
-                                "id": "CKV_CVE_2016_7401",
-                                "name": "SCA package scan",
-                                "shortDescription": {
-                                    "text": "CVE-2016-7401 - django: 1.2"
-                                }
-                            },
-                            {
-                                "defaultConfiguration": {
-                                    "level": "error"
-                                },
-                                "fullDescription": {
-                                    "text": "Django before 2.2.24, 3.x before 3.1.12, and 3.2.x before 3.2.4 has a potential directory traversal via django.contrib.admindocs. Staff members could use the TemplateDetailView view to check the existence of arbitrary files. Additionally, if (and only if) the default admindocs templates have been customized by application developers to also show file contents, then not only the existence but also the file contents would have been exposed. In other words, there is directory traversal outside of the template root directories."
-                                },
-                                "help": {
-                                    "text": "\"SCA package scan\nResource: path/to/requirements.txt.django\""
-                                },
-                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2021-33203",
-                                "id": "CKV_CVE_2021_33203",
-                                "name": "SCA package scan",
-                                "shortDescription": {
-                                    "text": "CVE-2021-33203 - django: 1.2"
-                                }
-                            },
-                            {
-                                "defaultConfiguration": {
-                                    "level": "error"
-                                },
-                                "fullDescription": {
-                                    "text": "The Pallets Project Flask before 1.0 is affected by: unexpected memory usage. The impact is: denial of service. The attack vector is: crafted encoded JSON data. The fixed version is: 1. NOTE: this may overlap CVE-2018-1000656."
-                                },
-                                "help": {
-                                    "text": "\"SCA package scan\nResource: path/to/requirements.txt.flask\""
-                                },
-                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2019-1010083",
-                                "id": "CKV_CVE_2019_1010083",
-                                "name": "SCA package scan",
-                                "shortDescription": {
-                                    "text": "CVE-2019-1010083 - flask: 0.6"
-                                }
-                            },
-                            {
-                                "defaultConfiguration": {
-                                    "level": "error"
-                                },
-                                "fullDescription": {
-                                    "text": "The Pallets Project flask version Before 0.12.3 contains a CWE-20: Improper Input Validation vulnerability in flask that can result in Large amount of memory usage possibly leading to denial of service. This attack appear to be exploitable via Attacker provides JSON data in incorrect encoding. This vulnerability appears to have been fixed in 0.12.3. NOTE: this may overlap CVE-2019-1010083."
-                                },
-                                "help": {
-                                    "text": "\"SCA package scan\nResource: path/to/requirements.txt.flask\""
-                                },
-                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2018-1000656",
-                                "id": "CKV_CVE_2018_1000656",
-                                "name": "SCA package scan",
-                                "shortDescription": {
-                                    "text": "CVE-2018-1000656 - flask: 0.6"
-                                }
-                            },
-                            {
-                                "defaultConfiguration": {
-                                    "level": "error"
-                                },
-                                "fullDescription": {
-                                    "text": "jwt-go before 4.0.0-preview1 allows attackers to bypass intended access restrictions in situations with []string{} for m[\\\"aud\\\"] (which is allowed by the specification). Because the type assertion fails, \\\"\\\" is the value of aud. This is a security problem if the JWT token is presented to a service that lacks its own audience check."
-                                },
-                                "help": {
-                                    "text": "\"SCA package scan\nResource: path/to/go.sum.github.com/dgrijalva/jwt-go\""
-                                },
-                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2020-26160",
-                                "id": "CKV_CVE_2020_26160",
-                                "name": "SCA package scan",
-                                "shortDescription": {
-                                    "text": "CVE-2020-26160 - github.com/dgrijalva/jwt-go: v3.2.0"
-                                }
-                            },
+                    },
+                    {
+                        "ruleId": "CVE-2020-29652_golang.org/x/crypto@v0.0.1",
+                        "ruleIndex": 8,
+                        "level": "error",
+                        "attachments": [],
+                        "message": {"text": "CVE-2020-29652 - golang.org/x/crypto: v0.0.1"},
+                        "locations": [
                             {
-                                "defaultConfiguration": {
-                                    "level": "error"
-                                },
-                                "fullDescription": {
-                                    "text": "A nil pointer dereference in the golang.org/x/crypto/ssh component through v0.0.3 for Go allows remote attackers to cause a denial of service against SSH servers."
-                                },
-                                "help": {
-                                    "text": "\"SCA package scan\nResource: path/to/go.sum.golang.org/x/crypto\""
-                                },
-                                "helpUri": "https://nvd.nist.gov/vuln/detail/CVE-2020-29652",
-                                "id": "CKV_CVE_2020_29652",
-                                "name": "SCA package scan",
-                                "shortDescription": {
-                                    "text": "CVE-2020-29652 - golang.org/x/crypto: v0.0.1"
+                                "physicalLocation": {
+                                    "artifactLocation": {"uri": "path/to/go.sum"},
+                                    "region": {
+                                        "startLine": 1,
+                                        "endLine": 1,
+                                        "snippet": {"text": "golang.org/x/crypto: v0.0.1"},
+                                    },
                                 }
                             }
                         ],
-                        "version": "2.0.x"
-                    }
-                }
+                        "suppressions": [{"kind": "external", "justification": "CVE-2020-29652 is skipped"}],
+                    },
+                ],
             }
         ],
-        "version": "2.1.0"
     }
     assert sarif_output == expected_sarif_json