diff --git a/__tests__/integration/ai-review.test.js b/__tests__/integration/ai-review.test.js index c792031..1e1c803 100644 --- a/__tests__/integration/ai-review.test.js +++ b/__tests__/integration/ai-review.test.js @@ -387,12 +387,42 @@ describe('ai-review', () => { expect(result).toContain('advisory only'); }); - it('sanitizes the AI response', () => { + it('sanitizes workflow commands in the AI response', () => { const result = formatReviewComment('Good code\n::set-output name=x::hack', 10); expect(result).toContain('[sanitized command]'); expect(result).not.toContain('::set-output'); }); + // Bug #29 — widen sanitiser + it('escapes HTML angle brackets so injected / ', + 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 — + * ``, `