路径验证
源码:
tools/PathValidation.ts|utils/paths.ts
1. 路径验证目的
确保 Claude Code 只能操作项目目录内的文件,防止意外修改系统文件或其他项目。
2. 验证机制
// 获取项目根目录
function getProjectRoot(): string {
// 1. 检查 .claude 目录
// 2. 回退到 git 根目录
// 3. 回退到当前工作目录
return resolveProjectRoot()
}
// 验证路径是否在项目范围内
function isPathAllowed(targetPath: string): boolean {
const root = getProjectRoot()
const resolved = path.resolve(root, targetPath)
return resolved.startsWith(root + '/') || resolved === root
}
3. 目录遍历保护
// 防御目录遍历攻击
function sanitizePath(input: string): string {
// 1. 规范化路径(解析 ../, ./, //)
const normalized = path.normalize(input)
// 2. 解析符号链接
const resolved = path.resolve(getProjectRoot(), normalized)
// 3. 检查是否逃逸项目目录
if (!resolved.startsWith(getProjectRoot())) {
throw new Error('路径超出项目范围')
}
return resolved
}
4. 符号链接处理
// 安全地跟随符号链接
async function safeResolveSymlink(linkPath: string): Promise<string> {
const stat = await fs.lstat(linkPath)
if (stat.isSymbolicLink()) {
const target = await fs.readlink(linkPath)
const resolved = path.resolve(path.dirname(linkPath), target)
// 验证符号链接目标也在项目目录内
if (!resolved.startsWith(getProjectRoot())) {
throw new Error('符号链接指向项目外部')
}
return resolved
}
return linkPath
}
5. 文件工具的路径检查
所有文件操作工具在调用前都经过路径验证:
// FileReadTool
async function call(input: FileReadInput) {
const safePath = sanitizePath(input.path)
// 安全检查通过后才读取
const content = await fs.readFile(safePath, 'utf-8')
return { content }
}
// FileWriteTool
async function call(input: FileWriteInput) {
const safePath = sanitizePath(input.path)
// 安全检查通过后才写入
await fs.writeFile(safePath, input.content)
return { success: true }
}
6. 特殊路径处理
| 路径 | 处理方式 |
|---|---|
~ | 展开为用户 HOME 目录,通常禁止访问 |
../ | 规范化后检查是否越界 |
/tmp | 临时目录通常允许 |
.env | 包含密钥的文件,特殊保护 |