From 99bf03960d0cd77088d51f6a09b41873f3add6a7 Mon Sep 17 00:00:00 2001 From: Sylvester Kaczmarek <16242628+sylvesterkaczmarek@users.noreply.github.com> Date: Tue, 18 Aug 2026 00:04:45 +0100 Subject: [PATCH 1/2] fix(plugin): preserve nested attack-path evidence in previews --- .../scripts/finding_preview.py | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/sdk/typescript/_bundled_plugin/scripts/finding_preview.py b/sdk/typescript/_bundled_plugin/scripts/finding_preview.py index 82d82e087..cc3921a0a 100644 --- a/sdk/typescript/_bundled_plugin/scripts/finding_preview.py +++ b/sdk/typescript/_bundled_plugin/scripts/finding_preview.py @@ -206,6 +206,7 @@ def bounded_finding_details(value: Any) -> dict[str, Any]: projected_core = bounded_json_value( core, [FINDING_DETAILS_PREVIEW_BYTES - reserved], + max_depth=5, ) if all(key in projected_core for key in core): break @@ -213,6 +214,7 @@ def bounded_finding_details(value: Any) -> dict[str, Any]: bounded = bounded_json_value( {**projected_core, **ordered_guidance, **extras}, [FINDING_DETAILS_PREVIEW_BYTES], + max_depth=5, ) return bounded if isinstance(bounded, dict) else {} @@ -262,10 +264,16 @@ def bounded_code_evidence(value: Any) -> Any: return bounded -def bounded_json_value(value: Any, budget: list[int], *, depth: int = 0) -> Any: +def bounded_json_value( + value: Any, + budget: list[int], + *, + depth: int = 0, + max_depth: int = 4, +) -> Any: if budget[0] <= 0: return None - if depth >= 4: + if depth >= max_depth: consume_json_budget(budget, 4) return None if isinstance(value, str): @@ -284,7 +292,12 @@ def bounded_json_value(value: Any, budget: list[int], *, depth: int = 0) -> Any: separator = 0 if not result else 1 if not consume_json_budget(budget, separator): break - bounded_item = bounded_json_value(item, budget, depth=depth + 1) + bounded_item = bounded_json_value( + item, + budget, + depth=depth + 1, + max_depth=max_depth, + ) size = len(json.dumps(bounded_item, separators=(",", ":")).encode("utf-8")) if separator + size > remaining or ( isinstance(item, str) and item and bounded_item == "" @@ -339,7 +352,12 @@ def bounded_json_value(value: Any, budget: list[int], *, depth: int = 0) -> Any: if budget[0] >= minimum_tests + reserved: item_budget = [budget[0] - reserved] break - bounded_item = bounded_json_value(item, item_budget, depth=depth + 1) + bounded_item = bounded_json_value( + item, + item_budget, + depth=depth + 1, + max_depth=max_depth, + ) size = ( separator + key_size From fb33ffcfc572d6960c152c7a755ce2a483875b72 Mon Sep 17 00:00:00 2001 From: Sylvester Kaczmarek <16242628+sylvesterkaczmarek@users.noreply.github.com> Date: Tue, 18 Aug 2026 00:04:58 +0100 Subject: [PATCH 2/2] test(plugin): cover nested attack-path preview evidence --- .../tests-ts/finding-preview.test.ts | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/sdk/typescript/tests-ts/finding-preview.test.ts b/sdk/typescript/tests-ts/finding-preview.test.ts index 974ab037d..0338a943c 100644 --- a/sdk/typescript/tests-ts/finding-preview.test.ts +++ b/sdk/typescript/tests-ts/finding-preview.test.ts @@ -62,4 +62,58 @@ describe("bundled finding previews", () => { original, }); }); + + test("preserves nested attack-path string arrays without relaxing section depth", () => { + const python = + Bun.which("python3") ?? Bun.which("python") ?? Bun.which("py"); + expect(python).not.toBeNull(); + + const original = { + supported: { + attackPath: { + dataflow: { evidenceRefs: ["source-to-sink"] }, + reachability: { preconditions: ["The handler is reachable."] }, + }, + }, + tooDeep: { + attackPath: { + dataflow: { + nested: { evidenceRefs: ["must remain depth-limited"] }, + }, + }, + }, + }; + const program = [ + "import json, sys", + "sys.path.insert(0, sys.argv[1])", + "from finding_preview import bounded_finding_details", + "original = json.loads(sys.argv[2])", + "projected = {name: bounded_finding_details(details) for name, details in original.items()}", + "print(json.dumps(projected))", + ].join("\n"); + const result = Bun.spawnSync( + [ + python!, + "-I", + "-B", + "-c", + program, + join(PLUGIN_ROOT, "scripts"), + JSON.stringify(original), + ], + { stdout: "pipe", stderr: "pipe" }, + ); + + expect(result.exitCode, new TextDecoder().decode(result.stderr)).toBe(0); + expect(JSON.parse(new TextDecoder().decode(result.stdout))).toEqual({ + supported: original.supported, + tooDeep: { + attackPath: { + dataflow: { + nested: { evidenceRefs: [null] }, + }, + }, + }, + }); + }); });