From 789e29bfd633605deb49e04fc8c5230ea2261a94 Mon Sep 17 00:00:00 2001 From: mangeshraut712 Date: Thu, 30 Jul 2026 23:11:07 +0530 Subject: [PATCH] fix: include informational findings in report.md projection informational is a valid findings severity and is exported to SARIF/CSV, but report.md filtered it out via REPORTABLE_SEVERITIES, so all- informational scans rendered as "No findings". Include informational in the reportable set and cover it with a projection unit test. Fixes #48 --- .../scripts/report_projection.py | 2 +- .../test_report_projection_informational.py | 79 +++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 sdk/typescript/_bundled_plugin/scripts/test_report_projection_informational.py diff --git a/sdk/typescript/_bundled_plugin/scripts/report_projection.py b/sdk/typescript/_bundled_plugin/scripts/report_projection.py index e1e9f45c..6eec4c34 100644 --- a/sdk/typescript/_bundled_plugin/scripts/report_projection.py +++ b/sdk/typescript/_bundled_plugin/scripts/report_projection.py @@ -13,7 +13,7 @@ SEVERITY_ORDER = {"critical": 0, "high": 1, "medium": 2, "low": 3, "informational": 4} CONFIDENCE_ORDER = {"high": 0, "medium": 1, "low": 2} -REPORTABLE_SEVERITIES = {"critical", "high", "medium", "low"} +REPORTABLE_SEVERITIES = {"critical", "high", "medium", "low", "informational"} DISPOSITION_LABELS = { "reported": "Reported", "no_issue_found": "No issue found", diff --git a/sdk/typescript/_bundled_plugin/scripts/test_report_projection_informational.py b/sdk/typescript/_bundled_plugin/scripts/test_report_projection_informational.py new file mode 100644 index 00000000..f1d08e3c --- /dev/null +++ b/sdk/typescript/_bundled_plugin/scripts/test_report_projection_informational.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +"""Guard: informational findings must appear in report.md projections.""" + +from __future__ import annotations + +import importlib.util +import unittest +from pathlib import Path + + +def load_report_projection(): + path = Path(__file__).with_name("report_projection.py") + spec = importlib.util.spec_from_file_location("report_projection", path) + assert spec is not None and spec.loader is not None + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +class InformationalReportProjectionTests(unittest.TestCase): + def test_informational_is_reportable(self) -> None: + module = load_report_projection() + self.assertIn("informational", module.REPORTABLE_SEVERITIES) + + def test_informational_only_scan_is_not_empty(self) -> None: + module = load_report_projection() + finding = { + "title": "Informational note", + "severity": { + "level": "informational", + "rationale": "Documented hardening opportunity.", + "changeConditions": "None.", + }, + "confidence": { + "level": "high", + "rationale": "Direct code evidence.", + }, + "taxonomy": {"category": "security-misconfiguration", "cwe": ["CWE-693"]}, + "summary": "An informational finding for projection coverage.", + "locations": [{"path": "README.md", "startLine": 1}], + "remediation": {"summary": "No urgent action required."}, + "validation": {"summary": "Validated against schema."}, + } + manifest = { + "scan": { + "target": { + "displayName": "demo", + "kind": "git", + "ref": "main", + "url": "https://example.com/demo.git", + }, + "scope": { + "summary": "Repository scan", + "includePaths": ["."], + "excludePaths": [], + "limitations": [], + "runtimeStatus": "not recorded", + "validationMode": "static", + }, + "threatModel": {"summary": "Demo threat model."}, + } + } + findings = {"findings": [finding]} + coverage = { + "mode": "repository", + "inventoryStrategy": "git", + "completeness": "complete", + "includePaths": ["."], + "excludePaths": [], + "explicitExclusions": [], + } + markdown = module.build_report_markdown(manifest, findings, coverage) + self.assertNotIn("### No findings", markdown) + self.assertIn("informational", markdown) + self.assertIn("Informational note", markdown) + + +if __name__ == "__main__": + unittest.main()