mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-15 14:23:02 -07:00
fix(core): refactor exit-plan-mode to use resolveAndValidatePlanPath consistently
This fixes unit test failures by centralizing path resolution logic.
This commit is contained in:
@@ -73,8 +73,10 @@ describe('ExitPlanModeTool', () => {
|
||||
|
||||
const createPlanFile = (name: string, content: string) => {
|
||||
const filePath = path.join(mockPlansDir, name);
|
||||
// Ensure parent directory exists for nested tests
|
||||
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
||||
fs.writeFileSync(filePath, content);
|
||||
return path.join('plans', name);
|
||||
return name;
|
||||
};
|
||||
|
||||
describe('shouldConfirmExecute', () => {
|
||||
|
||||
@@ -19,9 +19,13 @@ import type { MessageBus } from '../confirmation-bus/message-bus.js';
|
||||
import path from 'node:path';
|
||||
import type { Config } from '../config/config.js';
|
||||
import { EXIT_PLAN_MODE_TOOL_NAME } from './tool-names.js';
|
||||
import { validatePlanPath, validatePlanContent } from '../utils/planUtils.js';
|
||||
import {
|
||||
validatePlanPath,
|
||||
validatePlanContent,
|
||||
resolveAndValidatePlanPath,
|
||||
} from '../utils/planUtils.js';
|
||||
import { ApprovalMode } from '../policy/types.js';
|
||||
import { resolveToRealPath, isSubpath } from '../utils/paths.js';
|
||||
// Remove unused imports
|
||||
import { logPlanExecution } from '../telemetry/loggers.js';
|
||||
import { PlanExecutionEvent } from '../telemetry/types.js';
|
||||
import { getExitPlanModeDefinition } from './definitions/coreTools.js';
|
||||
@@ -59,16 +63,20 @@ export class ExitPlanModeTool extends BaseDeclarativeTool<
|
||||
if (!params.plan_filename || params.plan_filename.trim() === '') {
|
||||
return 'plan_filename is required.';
|
||||
}
|
||||
|
||||
const safeFilename = path.basename(params.plan_filename);
|
||||
const plansDir = resolveToRealPath(this.config.getPlansDir());
|
||||
const resolvedPath = path.join(this.config.getPlansDir(), safeFilename);
|
||||
|
||||
const realPath = resolveToRealPath(resolvedPath);
|
||||
|
||||
if (!isSubpath(plansDir, realPath)) {
|
||||
return `Access denied: plan path (${resolvedPath}) must be within the designated plans directory (${plansDir}).`;
|
||||
}
|
||||
try {
|
||||
resolveAndValidatePlanPath(
|
||||
params.plan_filename,
|
||||
this.config.getPlansDir(),
|
||||
);
|
||||
} catch (e) {
|
||||
if (e instanceof Error && e.message.startsWith('Security violation')) {
|
||||
return `Access denied: plan path (${path.join(
|
||||
this.config.getPlansDir(),
|
||||
params.plan_filename,
|
||||
)}) must be within the designated plans directory (${this.config.getPlansDir()}).`;
|
||||
}
|
||||
return e instanceof Error ? e.message : String(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user