From 31dca738d718c9d57d5706c375fa47b7d70d88e4 Mon Sep 17 00:00:00 2001 From: defalut <7101189+defalut@users.noreply.github.com> Date: Sun, 22 Feb 2026 22:23:40 +0100 Subject: [PATCH] Prevent grep tool from using match-all globs (leaks gitignored files) --- packages/opencode/src/tool/grep.ts | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/tool/grep.ts b/packages/opencode/src/tool/grep.ts index 00497d4e3f..5b1fa0b2a6 100644 --- a/packages/opencode/src/tool/grep.ts +++ b/packages/opencode/src/tool/grep.ts @@ -10,6 +10,19 @@ import { assertExternalDirectory } from "./external-directory" const MAX_LINE_LENGTH = 2000 +function normalizeInclude(include?: string) { + if (!include) return undefined + const v = include.trim() + if (!v) return undefined + + // Treat “match everything” globs as redundant. Passing them via --glob can + // act as an override/whitelist and may cause ignored paths to be searched. + const redundant = new Set(["*", "*.*", "**", "**/*", "./**", "./**/*"]) + if (redundant.has(v)) return undefined + + return v +} + export const GrepTool = Tool.define("grep", { description: DESCRIPTION, parameters: z.object({ @@ -22,6 +35,8 @@ export const GrepTool = Tool.define("grep", { throw new Error("pattern is required") } + const include = normalizeInclude(params.include) + await ctx.ask({ permission: "grep", patterns: [params.pattern], @@ -29,7 +44,7 @@ export const GrepTool = Tool.define("grep", { metadata: { pattern: params.pattern, path: params.path, - include: params.include, + include: include, }, }) @@ -39,8 +54,8 @@ export const GrepTool = Tool.define("grep", { const rgPath = await Ripgrep.filepath() const args = ["-nH", "--hidden", "--no-messages", "--field-match-separator=|", "--regexp", params.pattern] - if (params.include) { - args.push("--glob", params.include) + if (include) { + args.push("--glob", include) } args.push(searchPath)