**崩溃/挂死修复 (5):** - 统一 TrayManager.isQuitting 变量,修复 Cmd+Q 无法退出 - useAgentStream 闭包过期快照 → 每次 getState() - Agnes chatStream 添加 AbortSignal.timeout - SSE JSON.parse 添加 try-catch 保护 - Orchestrator setTools 污染 → save/restore 模式 **功能修复 (14):** - 上下文压缩实现 (每5轮 COMPRESSING 状态) - 修复 requestId 硬编码空串 - ConfigService.set() 保留已有 category - MemoryManager 新增 working 类型搜索 - PromptInjectionDefender 补全 sanitize() - Ollama: 补全 dynamicReminders + reasoningContent - openai-format: 所有 assistant 消息保留 reasoningContent - SSE: finish_reason 时提前 flush tool_calls - DeepSeek thinking effort 映射注释 - Ollama done_reason load→stop - RateLimitHook >= 边界修复 - WorkspaceService isValid 首次启动修复 - sessions:archive IPC handler - 托盘/窗口图标路径生产环境修复 **系统提示词优化:** - SOUL.md 存在时不显示兜底身份,原文放最前 - 兜底身份改为中文 (MetonaAI 自身描述) - 用户文本在前,附件内容在后 **文件上传:** - 非图片文件不再 base64 编码,保留 JSON 结构 - 用户文本优先于文件内容 **UI 修复:** - 首页 Logo 路径修复 (public/ + 相对路径) - TokenUsage contextWindow 动态计算 (Provider 感知) - 切换 Provider 同步 contextWindow - 托盘图标始终显示 Logo (状态由右键菜单展示)
103 lines
3.3 KiB
TypeScript
103 lines
3.3 KiB
TypeScript
/**
|
|
* Prompt Injection Defense — 提示注入防护系统
|
|
*
|
|
* 三层防御:
|
|
* 1. 正则快速过滤
|
|
* 2. 语义级检测(可选)
|
|
* 3. 指令隔离标记
|
|
*
|
|
* @see docs/生产级通用 AI Agent 智能体桌面应用:完整设计与构建指南.html — 第十章
|
|
*/
|
|
|
|
export interface InjectionDetectionResult {
|
|
isInjection: boolean;
|
|
riskScore: number; // 0-10
|
|
findings: InjectionFinding[];
|
|
recommendation: string;
|
|
}
|
|
|
|
export interface InjectionFinding {
|
|
pattern: string;
|
|
matched: string;
|
|
severity: 'low' | 'medium' | 'high';
|
|
}
|
|
|
|
export class PromptInjectionDefender {
|
|
private static INJECTION_PATTERNS = [
|
|
/ignore\s+(all\s+)?(previous|above|prior)\s+(instructions|commands|directives)/i,
|
|
/forget\s+(everything|all\s+(of\s+)?(the|your)|above)/i,
|
|
/you\s+are\s+now/i,
|
|
/new\s+(instructions|directive|role|persona)/i,
|
|
/override\s+your\s+/i,
|
|
/(show|display|print|output|reveal|tell\s+me)\s+(your|the)\s+(system\s+)?(prompt|instruction|directive)/i,
|
|
/(dump|echo|log|expose)\s+(your|the)\s+(context|memory|history)/i,
|
|
/-{3,}\s*(system|user|assistant|instruction)/i,
|
|
/<{3,}(system|instruction|prompt)/i,
|
|
/\[{3,}(system|instruction|prompt)/i,
|
|
/base64\s*:?\s*[A-Za-z0-9+/=]{20,}/i,
|
|
/pretend\s+(you\s+are|to\s+be)/i,
|
|
/act\s+as\s+(if\s+you\s+were|you're)/i,
|
|
/DAN\s*[:\[]/i,
|
|
/JAILBREAK/i,
|
|
];
|
|
|
|
detect(input: string): InjectionDetectionResult {
|
|
const findings: InjectionFinding[] = [];
|
|
let riskScore = 0;
|
|
|
|
for (const pattern of PromptInjectionDefender.INJECTION_PATTERNS) {
|
|
const matches = input.match(pattern);
|
|
if (matches) {
|
|
findings.push({
|
|
pattern: pattern.source,
|
|
matched: matches[0],
|
|
severity: this.classifySeverity(pattern.source),
|
|
});
|
|
riskScore += this.classifySeverity(pattern.source) === 'high' ? 3 :
|
|
this.classifySeverity(pattern.source) === 'medium' ? 2 : 1;
|
|
}
|
|
}
|
|
|
|
return {
|
|
isInjection: findings.length > 0,
|
|
riskScore: Math.min(10, riskScore),
|
|
findings,
|
|
recommendation: this.getRecommendation(riskScore),
|
|
};
|
|
}
|
|
|
|
private classifySeverity(pattern: string): 'low' | 'medium' | 'high' {
|
|
const highRiskKeywords = ['ignore', 'forget', 'jailbreak', 'DAN', 'override', 'new\\s+instruction'];
|
|
const mediumRiskKeywords = ['reveal', 'dump', 'pretend', 'act\\s+as'];
|
|
|
|
for (const kw of highRiskKeywords) {
|
|
if (new RegExp(kw, 'i').test(pattern)) return 'high';
|
|
}
|
|
for (const kw of mediumRiskKeywords) {
|
|
if (new RegExp(kw, 'i').test(pattern)) return 'medium';
|
|
}
|
|
return 'low';
|
|
}
|
|
|
|
/**
|
|
* 清理输入内容(移除明显的注入分隔符)
|
|
*/
|
|
sanitize(input: string): string {
|
|
let cleaned = input;
|
|
|
|
// 移除明显的分隔符注入
|
|
cleaned = cleaned.replace(/-{3,}\s*(system|user|assistant|instruction).*$/gim, '[REMOVED]');
|
|
cleaned = cleaned.replace(/<{3,}(system|instruction|prompt).*$/gim, '[REMOVED]');
|
|
cleaned = cleaned.replace(/\[{3,}(system|instruction|prompt).*$/gim, '[REMOVED]');
|
|
|
|
return cleaned.trim();
|
|
}
|
|
|
|
private getRecommendation(score: number): string {
|
|
if (score >= 7) return 'BLOCK: High-risk injection detected';
|
|
if (score >= 4) return 'WARN: Suspicious patterns found';
|
|
if (score >= 1) return 'LOG: Minor suspicious patterns detected';
|
|
return 'PASS: No injection patterns detected';
|
|
}
|
|
}
|