From 5beb933fc283f73c5f7ebd6899184bf841aac02e Mon Sep 17 00:00:00 2001 From: ghost <49853598+JSONbored@users.noreply.github.com> Date: Tue, 7 Jul 2026 00:37:56 -0700 Subject: [PATCH] fix(review): drop unsafe enrichment sections --- src/review/enrichment-wire.ts | 58 +++++++++++++++++++++++-------- test/unit/enrichment-wire.test.ts | 35 +++++++++++++++++++ 2 files changed, 78 insertions(+), 15 deletions(-) diff --git a/src/review/enrichment-wire.ts b/src/review/enrichment-wire.ts index 79ba8ddd8d..0af1d5f0bf 100644 --- a/src/review/enrichment-wire.ts +++ b/src/review/enrichment-wire.ts @@ -161,6 +161,45 @@ const REES_PROFILE_NAMES = ["fast", "balanced", "deep"] as const; type ReesProfileName = (typeof REES_PROFILE_NAMES)[number]; const REES_PROFILE_NAME_SET = new Set(REES_PROFILE_NAMES); +function markdownHeadingLevel(line: string): number | undefined { + const match = /^(#{1,6})\s+/.exec(line.trimStart()); + return match?.[1]?.length; +} + +function isPublicSafeEnrichmentLine(line: string): boolean { + try { + sanitizePublicComment(line); + return true; + } catch { + return false; + } +} + +function retainPublicSafeEnrichmentSections( + defanged: string, +): string | undefined { + const lines = defanged.split("\n"); + const safeLines: string[] = []; + for (let index = 0; index < lines.length; index += 1) { + const line = lines[index] ?? ""; + const headingLevel = markdownHeadingLevel(line); + if (isPublicSafeEnrichmentLine(line)) { + safeLines.push(line); + continue; + } + if (headingLevel === undefined) continue; + + while (index + 1 < lines.length) { + const nextLevel = markdownHeadingLevel(lines[index + 1] ?? ""); + if (nextLevel !== undefined && nextLevel <= headingLevel) break; + index += 1; + } + } + + const safeBlock = safeLines.join("\n").trim(); + return safeBlock || undefined; +} + function sanitizeEnrichmentPromptSection(value: unknown): string | undefined { if (typeof value !== "string") return undefined; const trimmed = value.trim(); @@ -172,21 +211,10 @@ function sanitizeEnrichmentPromptSection(value: unknown): string | undefined { MAX_ENRICHMENT_PROMPT_SECTION_CHARS, ); } catch { - const safeLines = defanged - .split("\n") - .filter((line) => { - try { - sanitizePublicComment(line); - return true; - } catch { - return false; - } - }) - .join("\n") - .trim(); - return safeLines - ? safeLines.slice(0, MAX_ENRICHMENT_PROMPT_SECTION_CHARS) - : undefined; + return retainPublicSafeEnrichmentSections(defanged)?.slice( + 0, + MAX_ENRICHMENT_PROMPT_SECTION_CHARS, + ); } } diff --git a/test/unit/enrichment-wire.test.ts b/test/unit/enrichment-wire.test.ts index e38dcad35f..fa0e48c69e 100644 --- a/test/unit/enrichment-wire.test.ts +++ b/test/unit/enrichment-wire.test.ts @@ -520,6 +520,41 @@ describe("buildReviewEnrichment", () => { expect(result?.systemSuffix).toContain("untrusted advisory context"); }); + it("drops non-public-safe enrichment sections with adjacent unlabeled values", async () => { + globalThis.fetch = vi.fn( + async () => + ({ + ok: true, + json: async () => ({ + promptSection: [ + "## EXTERNAL REVIEW BRIEF", + "### Dependency advisory", + "- package left-pad has CVE-2099-0001", + "### wallet", + "- adjacent unlabeled identifier", + "extra evidence without a forbidden label", + "### Safe follow-up", + "- retain public context", + ].join("\n"), + }), + }) as Response, + ) as unknown as typeof fetch; + + const result = await buildReviewEnrichment( + env({ REES_URL: "https://r" }), + input, + ); + + expect(result?.promptSection).toContain("## EXTERNAL REVIEW BRIEF"); + expect(result?.promptSection).toContain("### Dependency advisory"); + expect(result?.promptSection).toContain("### Safe follow-up"); + expect(result?.promptSection).not.toContain("### wallet"); + expect(result?.promptSection).not.toContain("adjacent unlabeled identifier"); + expect(result?.promptSection).not.toContain( + "extra evidence without a forbidden label", + ); + }); + it("undefined on a fetch throw (timeout/network) — fail-safe", async () => { globalThis.fetch = vi.fn(async () => { throw new Error("timeout");