feat: use secureFileService

This commit is contained in:
luojiyin 2025-08-21 17:41:49 +08:00
parent 8332734866
commit a0f772ea98
No known key found for this signature in database
GPG Key ID: 9F5399380CCFD0B3

View File

@ -1,8 +1,8 @@
import { ImageBlockParam } from '@anthropic-ai/sdk/resources/index.mjs' import { ImageBlockParam } from '@anthropic-ai/sdk/resources/index.mjs'
import { existsSync, readFileSync, statSync } from 'fs' import { statSync } from 'node:fs'
import { Box, Text } from 'ink' import { Box, Text } from 'ink'
import * as path from 'path' import * as path from 'node:path'
import { extname, relative } from 'path' import { extname, relative } from 'node:path'
import * as React from 'react' import * as React from 'react'
import { z } from 'zod' import { z } from 'zod'
import { FallbackToolUseRejectedMessage } from '../../components/FallbackToolUseRejectedMessage' import { FallbackToolUseRejectedMessage } from '../../components/FallbackToolUseRejectedMessage'
@ -24,6 +24,7 @@ import {
} from '../../services/fileFreshness' } from '../../services/fileFreshness'
import { DESCRIPTION, PROMPT } from './prompt' import { DESCRIPTION, PROMPT } from './prompt'
import { hasReadPermission } from '../../utils/permissions/filesystem' import { hasReadPermission } from '../../utils/permissions/filesystem'
import { secureFileService } from '../../utils/secureFile'
const MAX_LINES_TO_RENDER = 5 const MAX_LINES_TO_RENDER = 5
const MAX_OUTPUT_SIZE = 0.25 * 1024 * 1024 // 0.25MB in bytes const MAX_OUTPUT_SIZE = 0.25 * 1024 * 1024 // 0.25MB in bytes
@ -143,7 +144,9 @@ export const FileReadTool = {
async validateInput({ file_path, offset, limit }) { async validateInput({ file_path, offset, limit }) {
const fullFilePath = normalizeFilePath(file_path) const fullFilePath = normalizeFilePath(file_path)
if (!existsSync(fullFilePath)) { // Use secure file service to check if file exists and get file info
const fileCheck = secureFileService.safeGetFileInfo(fullFilePath)
if (!fileCheck.success) {
// Try to find a similar file with a different extension // Try to find a similar file with a different extension
const similarFilename = findSimilarFile(fullFilePath) const similarFilename = findSimilarFile(fullFilePath)
let message = 'File does not exist.' let message = 'File does not exist.'
@ -159,8 +162,7 @@ export const FileReadTool = {
} }
} }
// Get file stats to check size const stats = fileCheck.stats!
const stats = statSync(fullFilePath)
const fileSize = stats.size const fileSize = stats.size
const ext = path.extname(fullFilePath).toLowerCase() const ext = path.extname(fullFilePath).toLowerCase()
@ -315,7 +317,18 @@ async function readImage(
const sharp = ( const sharp = (
(await import('sharp')) as unknown as { default: typeof import('sharp') } (await import('sharp')) as unknown as { default: typeof import('sharp') }
).default ).default
const image = sharp(readFileSync(filePath))
// Use secure file service to read the file
const fileReadResult = secureFileService.safeReadFile(filePath, {
encoding: 'buffer' as BufferEncoding,
maxFileSize: MAX_IMAGE_SIZE
})
if (!fileReadResult.success) {
throw new Error(`Failed to read image file: ${fileReadResult.error}`)
}
const image = sharp(fileReadResult.content as Buffer)
const metadata = await image.metadata() const metadata = await image.metadata()
if (!metadata.width || !metadata.height) { if (!metadata.width || !metadata.height) {
@ -335,7 +348,17 @@ async function readImage(
width <= MAX_WIDTH && width <= MAX_WIDTH &&
height <= MAX_HEIGHT height <= MAX_HEIGHT
) { ) {
return createImageResponse(readFileSync(filePath), ext) // Use secure file service to read the file
const fileReadResult = secureFileService.safeReadFile(filePath, {
encoding: 'buffer' as BufferEncoding,
maxFileSize: MAX_IMAGE_SIZE
})
if (!fileReadResult.success) {
throw new Error(`Failed to read image file: ${fileReadResult.error}`)
}
return createImageResponse(fileReadResult.content as Buffer, ext)
} }
if (width > MAX_WIDTH) { if (width > MAX_WIDTH) {
@ -366,6 +389,15 @@ async function readImage(
} catch (e) { } catch (e) {
logError(e) logError(e)
// If any error occurs during processing, return original image // If any error occurs during processing, return original image
return createImageResponse(readFileSync(filePath), ext) const fileReadResult = secureFileService.safeReadFile(filePath, {
encoding: 'buffer' as BufferEncoding,
maxFileSize: MAX_IMAGE_SIZE
})
if (!fileReadResult.success) {
throw new Error(`Failed to read image file: ${fileReadResult.error}`)
}
return createImageResponse(fileReadResult.content as Buffer, ext)
} }
} }