diff --git a/packages/core/src/tools/memoryTool.test.ts b/packages/core/src/tools/memoryTool.test.ts index dcc9a14333..f050c7a0d9 100644 --- a/packages/core/src/tools/memoryTool.test.ts +++ b/packages/core/src/tools/memoryTool.test.ts @@ -86,8 +86,8 @@ describe('MemoryTool', () => { const newName = 'CUSTOM_CONTEXT.md'; setGeminiMdFilename(newName); expect(getAllGeminiMdFilenames()).toEqual([ - DEFAULT_CONTEXT_FILENAME, newName, + DEFAULT_CONTEXT_FILENAME, ]); }); @@ -104,8 +104,8 @@ describe('MemoryTool', () => { const newNames = ['CUSTOM_CONTEXT.md', 'ANOTHER_CONTEXT.md']; setGeminiMdFilename(newNames); expect(getAllGeminiMdFilenames()).toEqual([ - DEFAULT_CONTEXT_FILENAME, ...newNames, + DEFAULT_CONTEXT_FILENAME, ]); }); @@ -115,8 +115,8 @@ describe('MemoryTool', () => { setGeminiMdFilename(['NEW.md', 'NEW.md']); expect(getAllGeminiMdFilenames()).toEqual([ - DEFAULT_CONTEXT_FILENAME, 'NEW.md', + DEFAULT_CONTEXT_FILENAME, ]); }); }); diff --git a/packages/core/src/tools/memoryTool.ts b/packages/core/src/tools/memoryTool.ts index c9335b3594..923082fa02 100644 --- a/packages/core/src/tools/memoryTool.ts +++ b/packages/core/src/tools/memoryTool.ts @@ -49,8 +49,15 @@ export function setGeminiMdFilename(newFilename: string | string[]): void { for (const filename of filenames) { const trimmed = filename.trim(); if (trimmed !== '') { - const safeFilename = path.basename(trimmed); - next.add(safeFilename); + const normalized = path.normalize(trimmed); + // Sanitize to prevent path traversal while allowing subdirectories + if ( + !path.isAbsolute(normalized) && + !normalized.startsWith('..') && + normalized !== '.' + ) { + next.add(normalized); + } } } @@ -74,7 +81,16 @@ export function resetGeminiMdFilename( filename: string | string[] = DEFAULT_CONTEXT_FILENAME, ): void { const filenames = Array.isArray(filename) ? filename : [filename]; - const cleaned = filenames.map((f) => path.basename(f.trim())).filter((f) => f !== ''); + const cleaned = Array.from( + new Set( + filenames + .map((f) => path.normalize(f.trim())) + .filter( + (f) => + f !== '' && f !== '.' && !f.startsWith('..') && !path.isAbsolute(f), + ), + ), + ); if (cleaned.length === 0) { currentGeminiMdFilename = DEFAULT_CONTEXT_FILENAME;