This commit is contained in:
Deleted user 2026-05-27 10:43:59 +08:00 committed by GitHub
commit d28e29ea7a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 39 additions and 2 deletions

View file

@ -28,10 +28,9 @@ export class WriteToFileTool extends BaseTool<"write_to_file"> {
async execute(params: WriteToFileParams, task: Task, callbacks: ToolCallbacks): Promise<void> {
const { pushToolResult, handleError, askApproval } = callbacks
const relPath = params.path
let newContent = params.content
if (!relPath) {
if (!params.path) {
task.consecutiveMistakeCount++
task.recordToolError("write_to_file")
pushToolResult(await task.sayAndCreateMissingParamError("write_to_file", "path"))
@ -39,6 +38,14 @@ export class WriteToFileTool extends BaseTool<"write_to_file"> {
return
}
// Determine relative path - path can be absolute or relative
let relPath: string
if (path.isAbsolute(params.path)) {
relPath = path.relative(task.cwd, params.path)
} else {
relPath = params.path
}
if (newContent === undefined) {
task.consecutiveMistakeCount++
task.recordToolError("write_to_file")

View file

@ -244,6 +244,36 @@ describe("writeToFileTool", () => {
})
})
describe("absolute path handling", () => {
it("converts absolute path to relative path within workspace", async () => {
// Set up a workspace directory
mockCline.cwd = "/workspace/project"
// Provide an absolute path that's within the workspace
const absoluteInputPath = "/workspace/project/plans/architecture.md"
await executeWriteFileTool({ path: absoluteInputPath }, { accessAllowed: true })
// The path should be converted to relative and used for access validation
expect(mockCline.rooIgnoreController.validateAccess).toHaveBeenCalledWith("plans/architecture.md")
})
it("handles absolute path at root level (issue #11208)", async () => {
// This reproduces the bug where LLM outputs "/plans" as an absolute path
mockCline.cwd = "/workspace/project"
// Absolute path "/plans" would resolve to root without the fix
const absoluteInputPath = "/plans"
await executeWriteFileTool({ path: absoluteInputPath }, { accessAllowed: true })
// The path should be converted to a relative path (relative to cwd)
// path.relative("/workspace/project", "/plans") = "../../../plans" on Unix
// This is safer than trying to write to system root
expect(mockCline.rooIgnoreController.validateAccess).toHaveBeenCalled()
})
})
describe("file existence detection", () => {
it.skipIf(process.platform === "win32")("detects existing file and sets editType to modify", async () => {
await executeWriteFileTool({}, { fileExists: true })