refactor: integrate secure file system operations across services

This commit replaces direct file system operations with a secure file system adapter to enhance security by enforcing path validation. The changes include:

- Replaced `fs` imports with `secureFs` in various services and utilities.
- Updated file operations in `agent-service`, `auto-mode-service`, `feature-loader`, and `settings-service` to use the secure file system methods.
- Ensured that all file I/O operations are validated against the ALLOWED_ROOT_DIRECTORY.

This refactor aims to prevent unauthorized file access and improve overall security posture.

Tests: All unit tests passing.

🤖 Generated with Claude Code
This commit is contained in:
Test User
2025-12-20 18:45:39 -05:00
parent ade80484bb
commit f3c9e828e2
45 changed files with 329 additions and 551 deletions

View File

@@ -6,6 +6,7 @@
import { Router } from "express";
import type { AutoModeService } from "../../services/auto-mode-service.js";
import { validatePathParams } from "../../middleware/validate-paths.js";
import { createStopFeatureHandler } from "./routes/stop-feature.js";
import { createStatusHandler } from "./routes/status.js";
import { createRunFeatureHandler } from "./routes/run-feature.js";
@@ -22,16 +23,16 @@ export function createAutoModeRoutes(autoModeService: AutoModeService): Router {
router.post("/stop-feature", createStopFeatureHandler(autoModeService));
router.post("/status", createStatusHandler(autoModeService));
router.post("/run-feature", createRunFeatureHandler(autoModeService));
router.post("/run-feature", validatePathParams("projectPath"), createRunFeatureHandler(autoModeService));
router.post("/verify-feature", createVerifyFeatureHandler(autoModeService));
router.post("/resume-feature", createResumeFeatureHandler(autoModeService));
router.post("/context-exists", createContextExistsHandler(autoModeService));
router.post("/analyze-project", createAnalyzeProjectHandler(autoModeService));
router.post("/analyze-project", validatePathParams("projectPath"), createAnalyzeProjectHandler(autoModeService));
router.post(
"/follow-up-feature",
createFollowUpFeatureHandler(autoModeService)
);
router.post("/commit-feature", createCommitFeatureHandler(autoModeService));
router.post("/commit-feature", validatePathParams("projectPath", "worktreePath?"), createCommitFeatureHandler(autoModeService));
router.post("/approve-plan", createApprovePlanHandler(autoModeService));
return router;

View File

@@ -6,7 +6,6 @@ import type { Request, Response } from "express";
import type { AutoModeService } from "../../../services/auto-mode-service.js";
import { createLogger } from "../../../lib/logger.js";
import { getErrorMessage, logError } from "../common.js";
import { validatePath, PathNotAllowedError } from "../../../lib/security.js";
const logger = createLogger("AutoMode");
@@ -22,20 +21,6 @@ export function createAnalyzeProjectHandler(autoModeService: AutoModeService) {
return;
}
// Validate paths are within ALLOWED_ROOT_DIRECTORY
try {
validatePath(projectPath);
} catch (error) {
if (error instanceof PathNotAllowedError) {
res.status(403).json({
success: false,
error: error.message,
});
return;
}
throw error;
}
// Start analysis in background
autoModeService.analyzeProject(projectPath).catch((error) => {
logger.error(`[AutoMode] Project analysis error:`, error);

View File

@@ -5,7 +5,6 @@
import type { Request, Response } from "express";
import type { AutoModeService } from "../../../services/auto-mode-service.js";
import { getErrorMessage, logError } from "../common.js";
import { validatePath, PathNotAllowedError } from "../../../lib/security.js";
export function createCommitFeatureHandler(autoModeService: AutoModeService) {
return async (req: Request, res: Response): Promise<void> => {
@@ -26,23 +25,6 @@ export function createCommitFeatureHandler(autoModeService: AutoModeService) {
return;
}
// Validate paths are within ALLOWED_ROOT_DIRECTORY
try {
validatePath(projectPath);
if (worktreePath) {
validatePath(worktreePath);
}
} catch (error) {
if (error instanceof PathNotAllowedError) {
res.status(403).json({
success: false,
error: error.message,
});
return;
}
throw error;
}
const commitHash = await autoModeService.commitFeature(
projectPath,
featureId,

View File

@@ -6,7 +6,6 @@ import type { Request, Response } from "express";
import type { AutoModeService } from "../../../services/auto-mode-service.js";
import { createLogger } from "../../../lib/logger.js";
import { getErrorMessage, logError } from "../common.js";
import { validatePath, PathNotAllowedError } from "../../../lib/security.js";
const logger = createLogger("AutoMode");
@@ -27,20 +26,6 @@ export function createRunFeatureHandler(autoModeService: AutoModeService) {
return;
}
// Validate path is within ALLOWED_ROOT_DIRECTORY
try {
validatePath(projectPath);
} catch (error) {
if (error instanceof PathNotAllowedError) {
res.status(403).json({
success: false,
error: error.message,
});
return;
}
throw error;
}
// Start execution in background
// executeFeature derives workDir from feature.branchName
autoModeService