-
Notifications
You must be signed in to change notification settings - Fork 2.5k
fix: prevent file save before user approval when PREVENT_FOCUS_DISRUPTION is enabled #7684
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -202,6 +202,16 @@ export async function writeToFileTool( | |||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // Set up diffViewProvider properties needed for saveDirectly BEFORE asking for approval | ||||||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comment explains WHAT we're doing but not WHY it's critical for security. Could we make this more explicit? Something like:
Suggested change
|
||||||||||
| // This ensures we have the original content for comparison but don't write anything yet | ||||||||||
| cline.diffViewProvider.editType = fileExists ? "modify" : "create" | ||||||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I notice this block (lines 207-213) duplicates similar logic from the non-experiment path. Could we extract this into a helper function to reduce duplication? Something like |
||||||||||
| if (fileExists) { | ||||||||||
| const absolutePath = path.resolve(cline.cwd, relPath) | ||||||||||
| cline.diffViewProvider.originalContent = await fs.readFile(absolutePath, "utf-8") | ||||||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we add error handling here in case |
||||||||||
| } else { | ||||||||||
| cline.diffViewProvider.originalContent = "" | ||||||||||
| } | ||||||||||
|
|
||||||||||
| const completeMessage = JSON.stringify({ | ||||||||||
| ...sharedMessageProps, | ||||||||||
| content: newContent, | ||||||||||
|
|
@@ -210,19 +220,13 @@ export async function writeToFileTool( | |||||||||
| const didApprove = await askApproval("tool", completeMessage, undefined, isWriteProtected) | ||||||||||
|
|
||||||||||
| if (!didApprove) { | ||||||||||
| // Reset the diffViewProvider state since we're not proceeding | ||||||||||
| cline.diffViewProvider.editType = undefined | ||||||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good defensive programming! Properly resetting the state when the user rejects ensures no lingering state that could cause issues. |
||||||||||
| cline.diffViewProvider.originalContent = undefined | ||||||||||
| return | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // Set up diffViewProvider properties needed for saveDirectly | ||||||||||
| cline.diffViewProvider.editType = fileExists ? "modify" : "create" | ||||||||||
| if (fileExists) { | ||||||||||
| const absolutePath = path.resolve(cline.cwd, relPath) | ||||||||||
| cline.diffViewProvider.originalContent = await fs.readFile(absolutePath, "utf-8") | ||||||||||
| } else { | ||||||||||
| cline.diffViewProvider.originalContent = "" | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // Save directly without showing diff view or opening the file | ||||||||||
| // Only save directly AFTER user approval | ||||||||||
| await cline.diffViewProvider.saveDirectly(relPath, newContent, false, diagnosticsEnabled, writeDelayMs) | ||||||||||
| } else { | ||||||||||
| // Original behavior with diff view | ||||||||||
|
|
||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great test coverage for the happy path! Consider adding a test case for when
fs.readFilefails to ensure we handle that error scenario gracefully.