feat: MEMORY.md 访问保护、格式简化及预存问题修复
MEMORY.md 保护: 新建 file-guard.ts 共享守卫模块; read_file/write_file/search_files/run_command 禁止访问根目录 MEMORY.md; permissions.ts 增加 deniedPatterns 深度防御。格式简化: 元数据从 # 注释改为 > 引用语法; 校验规则从 6 条简化为 3 条; context-builder extractContent 适配。预存问题: 修复路径遍历前缀碰撞漏洞; 移除 browser_extract 内容截断; SearXNG 配置实时读取; web_search/web_fetch 移除截断; 侧边栏动态获取工具列表; 版本号 0.1.1
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* File Guard — 受保护文件守卫
|
||||
*
|
||||
* 确保工作空间根目录的 MEMORY.md 只能由系统内部(WorkspaceService)管理,
|
||||
* 任何工具(read_file / write_file / search_files / run_command 等)均禁止直接读写。
|
||||
*
|
||||
* 注意:仅保护工作空间根目录的 MEMORY.md,
|
||||
* 子目录或其他位置的同名文件不受限制。
|
||||
*/
|
||||
|
||||
import { resolve, sep } from 'path';
|
||||
|
||||
/**
|
||||
* 受保护文件名列表(工作空间根目录)
|
||||
*/
|
||||
const PROTECTED_FILES = ['MEMORY.md'];
|
||||
|
||||
/**
|
||||
* 检查目标路径是否为工作空间根目录的受保护文件
|
||||
*
|
||||
* @param filePath 用户传入的文件路径(绝对或相对)
|
||||
* @param workspacePath 当前工作空间根路径
|
||||
* @returns true 如果路径指向受保护文件
|
||||
*/
|
||||
export function isProtectedWorkspaceFile(
|
||||
filePath: string,
|
||||
workspacePath: string,
|
||||
): boolean {
|
||||
const resolved = resolve(workspacePath, filePath);
|
||||
const workspaceRoot = resolve(workspacePath);
|
||||
|
||||
for (const protectedName of PROTECTED_FILES) {
|
||||
const protectedPath = resolve(workspaceRoot, protectedName);
|
||||
if (resolved === protectedPath) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查路径是否在工作空间内(防止路径遍历攻击)
|
||||
*
|
||||
* 修复前缀碰撞漏洞:`/home/user/app-evil` 不应被误判为在 `/home/user/app` 内。
|
||||
*
|
||||
* @param filePath 用户传入的文件路径
|
||||
* @param workspacePath 当前工作空间根路径
|
||||
* @returns true 如果路径在工作空间内
|
||||
*/
|
||||
export function isPathWithinWorkspace(
|
||||
filePath: string,
|
||||
workspacePath: string,
|
||||
): boolean {
|
||||
const resolved = resolve(workspacePath, filePath);
|
||||
const workspaceRoot = resolve(workspacePath);
|
||||
return resolved === workspaceRoot || resolved.startsWith(workspaceRoot + sep);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查命令字符串是否尝试访问工作空间根目录的受保护文件
|
||||
*
|
||||
* 用于 run_command 工具的命令校验。
|
||||
* 采用大小写不敏感匹配,覆盖 cat/type/Get-Content 等常见读取命令。
|
||||
*
|
||||
* @param command Shell 命令字符串
|
||||
* @returns true 如果命令包含受保护文件名
|
||||
*/
|
||||
export function commandTouchesProtectedFile(command: string): boolean {
|
||||
const lowerCmd = command.toLowerCase();
|
||||
for (const protectedName of PROTECTED_FILES) {
|
||||
if (lowerCmd.includes(protectedName.toLowerCase())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user