From 13d6c598ee2905db7cba8a7f41999d7e6cfbfc51 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sat, 18 Apr 2026 01:55:18 +0000 Subject: [PATCH 1/2] fix: validate reviewAgentLogPath to prevent path injection Add path validation in invokeDiffReviewLlm to ensure the log file path stays within the expected review-agent directory. This prevents potential path traversal attacks by validating that the resolved path starts with the expected base directory (DATA_CACHE_DIR/review-agent). Fixes CodeQL js/path-injection alerts #18 and #19. Co-authored-by: Michael Sukkarieh --- .../review-agent/nodes/invokeDiffReviewLlm.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/web/src/features/agents/review-agent/nodes/invokeDiffReviewLlm.ts b/packages/web/src/features/agents/review-agent/nodes/invokeDiffReviewLlm.ts index f3f41be80..0b9a7d1e2 100644 --- a/packages/web/src/features/agents/review-agent/nodes/invokeDiffReviewLlm.ts +++ b/packages/web/src/features/agents/review-agent/nodes/invokeDiffReviewLlm.ts @@ -2,10 +2,20 @@ import OpenAI from "openai"; import { sourcebot_file_diff_review, sourcebot_file_diff_review_schema } from "@/features/agents/review-agent/types"; import { env } from "@sourcebot/shared"; import fs from "fs"; +import path from "path"; import { createLogger } from "@sourcebot/shared"; const logger = createLogger('invoke-diff-review-llm'); +const REVIEW_AGENT_LOG_BASE = path.join(env.DATA_CACHE_DIR, 'review-agent'); + +const validateReviewAgentLogPath = (logPath: string): void => { + const resolved = path.resolve(logPath); + if (!resolved.startsWith(REVIEW_AGENT_LOG_BASE + path.sep)) { + throw new Error('reviewAgentLogPath escapes log directory'); + } +}; + export const invokeDiffReviewLlm = async (reviewAgentLogPath: string | undefined, prompt: string): Promise => { logger.debug("Executing invoke_diff_review_llm"); @@ -13,6 +23,10 @@ export const invokeDiffReviewLlm = async (reviewAgentLogPath: string | undefined logger.error("OPENAI_API_KEY is not set, skipping review agent"); throw new Error("OPENAI_API_KEY is not set, skipping review agent"); } + + if (reviewAgentLogPath) { + validateReviewAgentLogPath(reviewAgentLogPath); + } const openai = new OpenAI({ apiKey: env.OPENAI_API_KEY, From fedc25ff2c51599f63326fe47dace17b023356ac Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sat, 18 Apr 2026 01:55:56 +0000 Subject: [PATCH 2/2] docs: add CHANGELOG entry for path injection fix Co-authored-by: Michael Sukkarieh --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 454eebecd..9ee901e75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Fixed revision selection so the 64-revision cap prefers the newest matching branches and tags instead of pruning by ref-name order. [#1122](https://github.com/sourcebot-dev/sourcebot/pull/1122) - Fixed infinite pagination loop in Gitea/Forgejo when an API token can only see a subset of org repos (the `x-total-count` header reports org total while token returns fewer items). [#1130](https://github.com/sourcebot-dev/sourcebot/pull/1130) +- Fixed CodeQL path injection vulnerability in review agent log file writing by validating paths stay within the expected log directory. [#1133](https://github.com/sourcebot-dev/sourcebot/pull/1133) ## [4.16.11] - 2026-04-17