From 5060f58d2ef82d7a6a18cf312f45d0c82c406a7d Mon Sep 17 00:00:00 2001 From: Ralf Anton Beier Date: Fri, 1 May 2026 20:10:55 +0200 Subject: [PATCH] fix: widen sanitizeAIOutput to cover HTML and @mentions (Bug #29) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Why: wave-1 LLM and Security agents flagged the previous one-pattern sanitiser (workflow commands only) as too narrow. AI model output is embedded directly in PR comments — an attacker controlling the diff content could inject ``, `', + 11 + ); + expect(result).not.toMatch(/ { + const result = formatReviewComment( + 'cc @octocat please review, also @pulseengine/maintainers', + 12 + ); + // The @ remains visible to humans but the username is preceded by a + // zero-width space (\u200B), preventing GitHub from creating a mention. + expect(result).toContain('@\u200Boctocat'); + expect(result).toContain('@\u200Bpulseengine/maintainers'); + expect(result).not.toMatch(/(? { + // `foo@example.com` is not a GitHub username pattern; let it through. + const result = formatReviewComment('Contact foo@example.com', 13); + expect(result).toContain('foo'); + }); + it('includes local AI model attribution', () => { const result = formatReviewComment('Review text', 1); expect(result).toContain('local AI model'); diff --git a/src/ai-review.js b/src/ai-review.js index ea12e4f..30dd3d2 100644 --- a/src/ai-review.js +++ b/src/ai-review.js @@ -65,9 +65,41 @@ function isLocalEndpoint(endpoint) { } } +/** + * Strip patterns that an attacker-influenced PR diff could exploit through + * the AI model's output. Wave-1 LLM and Security agents flagged the + * previous one-pattern version (workflow-commands only) as too narrow — + * Bug #29 in `docs/agent-fleet/bugs.md`. + * + * Concretely, attacker patterns we now neutralise: + * + * 1. GitHub Actions workflow commands (`::set-output ::`, `::error ::`) + * — could escape into a runner that consumes bot comments. + * 2. HTML elements that GitHub renders inside Markdown comments — + * ``, `