# How the code-review-graph Refactor Tool Handles Rename Previews and Apply Operations Securely

> Learn how the code-review-graph refactor tool securely handles rename previews and applies changes using a two-phase workflow, sandboxed webviews, and atomic operations.

- Repository: [Tirth Kanani/code-review-graph](https://github.com/tirth8205/code-review-graph)
- Tags: how-to-guide
- Published: 2026-07-29

---

**The refactor tool implements a two-phase workflow that separates preview generation from destructive changes, using sandboxed webviews, temporary staging directories with SHA-256 checksums, and atomic file operations to prevent data corruption and workspace escape vulnerabilities.**

The **code-review-graph** extension provides sophisticated refactoring capabilities that ensure **rename previews and apply operations are handled securely** through a defense-in-depth architecture. By separating read-only analysis from write operations and confining all filesystem interactions to a temporary staging area, the tool protects against path traversal attacks, partial writes, and accidental data loss while maintaining an interactive user experience.

## The Two-Phase Refactor Architecture

The rename workflow is explicitly divided into distinct preview and apply phases to ensure user intent is verified before any filesystem modification occurs.

### Phase 1: Building the Rename Preview

During the preview phase, the tool performs a complete scan of the code graph to locate every reference to the symbol targeted for renaming. It constructs a rename transaction entirely in memory, producing a detailed report that lists affected files, line numbers, and the exact text changes that would occur. **No file on disk is touched during this phase.**

Security measures in the preview phase include:

- **In-memory processing**: All analysis data remains in RAM; the preview never writes to the filesystem
- **Path sanitization**: Any path not under the VS Code workspace root is discarded immediately, preventing path-traversal attacks
- **Sandboxed rendering**: The preview report displays through VS Code’s Webview API in a sandboxed iframe, isolating the UI from the extension host

### Phase 2: Secure Apply Operations

When the user confirms the preview by clicking *Apply*, the tool transitions to the destructive phase. Rather than modifying original files directly, it creates a **temporary staging directory** using `fs.mkdtemp`, writes changes to copies in this isolated location, performs cryptographic verification, and then executes atomic renames.

This phase implements several integrity guarantees:

- **Staging isolation**: All writes occur in the temporary directory until verification passes
- **Checksum validation**: SHA-256 hashes verify file integrity before commitment
- **Atomic replacement**: `fs.renameSync` ensures that changes appear either completely or not at all, eliminating half-finished states
- **Workspace confinement**: All file-system actions resolve paths relative to `vscode.workspace.getWorkspaceFolder`, preventing access outside the project boundary

## Security Mechanisms in Detail

### Workspace Confinement and Path Sanitization

The extension strictly scopes all file operations to the current workspace root. Before processing any file path, the system validates that it falls within the directory returned by `vscode.workspace.getWorkspaceFolder`. Paths that resolve outside this boundary are rejected immediately, ensuring the extension cannot access system files or other projects.

### Staging, Checksums, and Atomic Renames

The staging implementation in [`src/features/refactor.ts`](https://github.com/tirth8205/code-review-graph/blob/main/src/features/refactor.ts) follows a defensive sequence:

1. **Temporary directory creation**: Uses `fs.promises.mkdtemp` with a `crg-` prefix to create an isolated working area
2. **Content staging**: Writes proposed changes to temporary copies rather than originals
3. **Cryptographic verification**: Computes SHA-256 checksums of staged content and compares them against expected values before proceeding
4. **Atomic commit**: Uses `fs.promises.rename` to move staging files over originals, leveraging POSIX atomicity guarantees

If checksum verification fails at any point, the operation aborts completely and VS Code displays an error dialog, leaving original files untouched.

### Isolated Preview Rendering

The preview UI renders inside a VS Code webview, which executes in a sandboxed iframe with restricted privileges. Communication between the webview and the extension host occurs exclusively through the `vscode.postMessage` API, ensuring that malicious content in the preview cannot access the Node.js filesystem APIs or extension context.

## Core Implementation Files

### CLI Wrapper ([`src/backend/cli.ts`](https://github.com/tirth8205/code-review-graph/blob/main/src/backend/cli.ts))

The `CliWrapper` class provides the interface between the VS Code extension and the command-line refactor tool. It launches the refactor sub-command (`code-review-graph refactor …`) within a VS Code progress notification and standardizes return values as `{ success, stdout, stderr }` objects. This abstraction ensures consistent error handling across both preview and apply operations.

### Transaction Builder ([`src/features/refactor.ts`](https://github.com/tirth8205/code-review-graph/blob/main/src/features/refactor.ts))

This module contains the **transaction builder** that walks the code graph to collect rename candidates and construct the preview JSON. It also implements the critical staging logic: writing to temporary copies, validating SHA-256 checksums, and executing the atomic replace sequence. This file coordinates with [`src/features/blastRadius.ts`](https://github.com/tirth8205/code-review-graph/blob/main/src/features/blastRadius.ts) to determine the impact radius of a rename, ensuring only relevant files enter the transaction.

### Webview Interface ([`src/views/graphWebview.ts`](https://github.com/tirth8205/code-review-graph/blob/main/src/views/graphWebview.ts))

Responsible for rendering the preview UI, this file creates the sandboxed webview panel and manages message passing. When the user clicks *Apply*, it forwards the command to the extension host via `vscode.postMessage`, triggering the secure apply workflow without exposing filesystem paths to the renderer.

## Practical Code Examples

### Triggering a Rename Preview

The following TypeScript demonstrates how the extension initiates a dry-run preview through the command palette:

```typescript
// Triggered by VS Code command: codeReviewGraph.refactorRename
async function runRenamePreview(oldName: string, newName: string) {
  const cli = new CliWrapper();               // from src/backend/cli.ts
  const args = ['refactor', 'rename', '--dry-run', oldName, newName];
  const result = await cli.exec(args, vscode.workspace.rootPath!);
  
  if (result.success) {
    // Send JSON to webview for display
    graphWebview.postMessage({ 
      type: 'preview', 
      payload: JSON.parse(result.stdout) 
    });
  } else {
    vscode.window.showErrorMessage(result.stderr);
  }
}

```

### Handling User Confirmation and Apply

This code runs inside the webview's message handler to securely forward the apply command:

```typescript
// Inside src/views/graphWebview.ts message handler
window.addEventListener('message', async (event) => {
  if (event.data.type === 'applyRename') {
    const { oldName, newName } = event.data.payload;
    const cli = new CliWrapper();
    const args = ['refactor', 'rename', oldName, newName];  // no --dry-run flag
    
    const result = await cli.exec(args, vscode.workspace.rootPath!);
    
    if (result.success) {
      vscode.window.showInformationMessage('Rename applied successfully');
    } else {
      vscode.window.showErrorMessage(`Rename failed: ${result.stderr}`);
    }
  }
});

```

### Core Staging and Verification Logic

The following simplified implementation from [`src/features/refactor.ts`](https://github.com/tirth8205/code-review-graph/blob/main/src/features/refactor.ts) demonstrates the checksum verification and atomic replacement strategy:

```typescript
// Inside src/features/refactor.ts
async function applyRenameTransaction(changes: RenameChange[]) {
  const tmpDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'crg-'));
  const hashes: Record<string, string> = {};

  // 1. Write staged copies and compute checksums
  for (const { file, newContent } of changes) {
    const stagingPath = path.join(tmpDir, path.basename(file));
    await fs.promises.writeFile(stagingPath, newContent);
    hashes[stagingPath] = crypto.createHash('sha256')
                                 .update(newContent)
                                 .digest('hex');
  }

  // 2. Verify checksums before committing
  for (const { file } of changes) {
    const stagingPath = path.join(tmpDir, path.basename(file));
    const expected = hashes[stagingPath];
    const actual = crypto.createHash('sha256')
                         .update(await fs.promises.readFile(stagingPath))
                         .digest('hex');
    if (expected !== actual) {
      throw new Error(`Checksum mismatch for ${file}`);
    }
  }

  // 3. Atomic replace
  for (const { file } of changes) {
    const stagingPath = path.join(tmpDir, path.basename(file));
    await fs.promises.rename(stagingPath, file);   // atomic on POSIX
  }
}

```

## Summary

- **Two-phase separation** ensures preview operations are read-only and apply operations require explicit user confirmation
- **SHA-256 checksums** validate file integrity between staging and commitment, preventing corruption from disk errors or race conditions
- **Atomic rename operations** guarantee that file updates appear completely or not at all, eliminating partial modification states
- **Workspace root scoping** combined with path sanitization prevents the extension from accessing files outside the project directory
- **Sandboxed webview rendering** isolates the preview UI from filesystem APIs, protecting against injection attacks

## Frequently Asked Questions

### How does the tool prevent modification of files outside the workspace?

The extension retrieves the workspace root using `vscode.workspace.getWorkspaceFolder` and validates every target path against this boundary before inclusion in the rename transaction. Any path resolving outside the workspace is discarded during the preview generation phase, effectively preventing path-traversal attacks.

### What happens if the extension crashes during the apply phase?

Because the tool writes all changes to a temporary staging directory first and only modifies originals after successful checksum verification, a crash at any point leaves the original files untouched. The temporary directory uses the `crg-` prefix and is created via `fs.mkdtemp`, ensuring that system cleanup processes can remove orphaned staging files if the extension terminates unexpectedly.

### Why does the tool use SHA-256 checksums rather than simple timestamp or size comparisons?

SHA-256 provides cryptographic assurance that the content written to the staging directory matches exactly what was computed during the transaction building phase. This protects against subtle corruption from cosmic rays, disk faults, or memory errors that simpler metadata checks might miss, ensuring that only verified content replaces original files.

### Can users preview renames without the risk of accidental application?

Yes. The preview phase runs with the `--dry-run` flag and operates entirely in memory without filesystem writes. The apply phase requires a separate explicit action—clicking the *Apply* button in the sandboxed webview—which sends a distinct message type to the extension host. This architectural separation ensures that viewing a preview can never trigger accidental modifications.