流式渲染修复: - runId 机制防止 abort 后旧流事件污染新 run - run lock 防止并发 run 污染引擎状态 - abort race 提前退出工具执行等待 - TERMINATED 状态通过 stateChange 发射 - tool_call_delta 流式参数拼接 + pending 占位替换 - 首轮卡片创建路径统一,traceStep 按 ID 精确匹配 - compressed 事件转发为 toast 通知 安全增强: - ConfirmationHook 支持持久化自动执行(跨会话) - 设置面板新增自动执行工具管理 UI - SandboxManager 双重安全校验 fail-closed - 审计日志链式哈希防篡改 - PromptInjectionDefender 中文注入标记清理 - scanCode 28 模式 + base64/$() 检测 - validatePath realpathSync 防符号链接逃逸 - code-search 使用 execFile 防命令注入 新增工具: - file_editor、code_search、task_manager、diff_viewer 其他: - Agent Loop 加 PARSING/REFLECTING 状态 + 指数退避重试 - MemoryManager TF-IDF 语义检索 - run_command Windows 中文编码修复(chcp 65001) - 版本号 0.2.0 → 0.2.1
109 lines
3.8 KiB
TypeScript
109 lines
3.8 KiB
TypeScript
/**
|
|
* Policy Engine — 权限策略引擎
|
|
*
|
|
* 三级权限模型:Read / Write / External Action
|
|
*
|
|
* @see docs/生产级通用 AI Agent 智能体桌面应用:完整设计与构建指南.html — 第十章
|
|
*/
|
|
|
|
export enum PermissionLevel {
|
|
READ = 'read',
|
|
WRITE = 'write',
|
|
EXTERNAL_ACTION = 'external',
|
|
}
|
|
|
|
export interface PermissionPolicy {
|
|
toolName: string;
|
|
requiredLevel: PermissionLevel;
|
|
allowedPatterns?: RegExp[];
|
|
deniedPatterns?: RegExp[];
|
|
maxFrequency?: number;
|
|
requireConfirmation?: boolean;
|
|
}
|
|
|
|
export const DEFAULT_POLICIES: PermissionPolicy[] = [
|
|
{ toolName: 'read_file', requiredLevel: PermissionLevel.READ, deniedPatterns: [/\/etc\//, /\/proc\//, /C:\\Windows\\/i, /C:\\System32\\/i, /MEMORY\.md/i] },
|
|
{ toolName: 'web_search', requiredLevel: PermissionLevel.READ, maxFrequency: 10 },
|
|
{ toolName: 'list_directory', requiredLevel: PermissionLevel.READ },
|
|
{ toolName: 'search_files', requiredLevel: PermissionLevel.READ },
|
|
{ toolName: 'memory_search', requiredLevel: PermissionLevel.READ },
|
|
{ toolName: 'write_file', requiredLevel: PermissionLevel.WRITE, deniedPatterns: [/\/etc\//, /\/proc\//, /\/System\//, /C:\\Windows\\/i, /C:\\System32\\/i, /MEMORY\.md/i], requireConfirmation: true, maxFrequency: 5 },
|
|
{ toolName: 'memory_store', requiredLevel: PermissionLevel.WRITE },
|
|
{ toolName: 'run_command', requiredLevel: PermissionLevel.EXTERNAL_ACTION, deniedPatterns: [/MEMORY\.md/i], requireConfirmation: true, maxFrequency: 3 },
|
|
{ toolName: 'web_fetch', requiredLevel: PermissionLevel.READ },
|
|
// web_browser — 统一浏览器工具(合并自 9 个独立 browser_* 工具)
|
|
// 由于该工具可执行 JS、点击元素等高风险操作,统一设为 EXTERNAL_ACTION
|
|
{ toolName: 'web_browser', requiredLevel: PermissionLevel.EXTERNAL_ACTION, requireConfirmation: true, maxFrequency: 20 },
|
|
];
|
|
|
|
export class PolicyEngine {
|
|
private policies: Map<string, PermissionPolicy> = new Map();
|
|
|
|
constructor(customPolicies: PermissionPolicy[] = []) {
|
|
for (const policy of DEFAULT_POLICIES) {
|
|
this.policies.set(policy.toolName, policy);
|
|
}
|
|
for (const policy of customPolicies) {
|
|
this.policies.set(policy.toolName, policy);
|
|
}
|
|
}
|
|
|
|
checkAuthorization(toolName: string, args: Record<string, unknown>): {
|
|
authorized: boolean;
|
|
reason?: string;
|
|
level: PermissionLevel;
|
|
requiresConfirmation: boolean;
|
|
} {
|
|
const policy = this.policies.get(toolName);
|
|
|
|
if (!policy) {
|
|
return {
|
|
authorized: false,
|
|
reason: `No policy configured for tool: ${toolName}`,
|
|
level: PermissionLevel.EXTERNAL_ACTION,
|
|
requiresConfirmation: true,
|
|
};
|
|
}
|
|
|
|
const argsStr = JSON.stringify(args);
|
|
|
|
// v0.2.0: allowedPatterns 白名单校验 — 若定义了白名单,参数必须匹配其中之一
|
|
if (policy.allowedPatterns && policy.allowedPatterns.length > 0) {
|
|
let matchedAllowed = false;
|
|
for (const pattern of policy.allowedPatterns) {
|
|
if (pattern.test(argsStr)) {
|
|
matchedAllowed = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!matchedAllowed) {
|
|
return {
|
|
authorized: false,
|
|
reason: 'Arguments do not match any allowed pattern',
|
|
level: policy.requiredLevel,
|
|
requiresConfirmation: policy.requireConfirmation ?? false,
|
|
};
|
|
}
|
|
}
|
|
|
|
if (policy.deniedPatterns) {
|
|
for (const pattern of policy.deniedPatterns) {
|
|
if (pattern.test(argsStr)) {
|
|
return {
|
|
authorized: false,
|
|
reason: 'Command blocked by security policy',
|
|
level: policy.requiredLevel,
|
|
requiresConfirmation: false,
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
authorized: true,
|
|
level: policy.requiredLevel,
|
|
requiresConfirmation: policy.requireConfirmation ?? false,
|
|
};
|
|
}
|
|
}
|