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

@@ -5,6 +5,7 @@
import { Router } from "express";
import { AgentService } from "../../services/agent-service.js";
import type { EventEmitter } from "../../lib/events.js";
import { validatePathParams } from "../../middleware/validate-paths.js";
import { createStartHandler } from "./routes/start.js";
import { createSendHandler } from "./routes/send.js";
import { createHistoryHandler } from "./routes/history.js";
@@ -18,8 +19,8 @@ export function createAgentRoutes(
): Router {
const router = Router();
router.post("/start", createStartHandler(agentService));
router.post("/send", createSendHandler(agentService));
router.post("/start", validatePathParams("workingDirectory?"), createStartHandler(agentService));
router.post("/send", validatePathParams("workingDirectory?", "imagePaths[]"), createSendHandler(agentService));
router.post("/history", createHistoryHandler(agentService));
router.post("/stop", createStopHandler(agentService));
router.post("/clear", createClearHandler(agentService));

View File

@@ -6,8 +6,6 @@ import type { Request, Response } from "express";
import { AgentService } from "../../../services/agent-service.js";
import { createLogger } from "../../../lib/logger.js";
import { getErrorMessage, logError } from "../common.js";
import { validatePath, PathNotAllowedError } from "../../../lib/security.js";
const logger = createLogger("Agent");
export function createSendHandler(agentService: AgentService) {
@@ -30,27 +28,6 @@ export function createSendHandler(agentService: AgentService) {
return;
}
// Validate paths are within ALLOWED_ROOT_DIRECTORY
try {
if (workingDirectory) {
validatePath(workingDirectory);
}
if (imagePaths && imagePaths.length > 0) {
for (const imagePath of imagePaths) {
validatePath(imagePath);
}
}
} catch (error) {
if (error instanceof PathNotAllowedError) {
res.status(403).json({
success: false,
error: error.message,
});
return;
}
throw error;
}
// Start the message processing (don't await - it streams via WebSocket)
agentService
.sendMessage({

View File

@@ -6,8 +6,6 @@ import type { Request, Response } from "express";
import { AgentService } from "../../../services/agent-service.js";
import { createLogger } from "../../../lib/logger.js";
import { getErrorMessage, logError } from "../common.js";
import { validatePath, PathNotAllowedError } from "../../../lib/security.js";
const logger = createLogger("Agent");
export function createStartHandler(agentService: AgentService) {
@@ -25,22 +23,6 @@ export function createStartHandler(agentService: AgentService) {
return;
}
// Validate paths are within ALLOWED_ROOT_DIRECTORY
if (workingDirectory) {
try {
validatePath(workingDirectory);
} catch (error) {
if (error instanceof PathNotAllowedError) {
res.status(403).json({
success: false,
error: error.message,
});
return;
}
throw error;
}
}
const result = await agentService.startConversation({
sessionId,
workingDirectory,