@yottameta/yotta-verify-mcp-plugin 0.0.0 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,449 @@
1
+ # -*- coding: utf-8 -*-
2
+ """verify_rules.py — yotta-verify(元信)装前扫描规则表。
3
+
4
+ 结构:
5
+ - AUDIT_PATTERN_RULES:与 yotta-security-audit/scripts/audit_rules.py 的 PATTERN_RULES
6
+ 同步副本(勿手改;由 YottaSkills 仓库 tools/sync-verify-rules.py 更新,改规则请改
7
+ yotta-security-audit/scripts/audit_rules.py)。
8
+ - PIJ_PATTERN_RULES:元信独有 Prompt Injection(提示注入)规则,手工维护。
9
+ - PATTERN_RULES = AUDIT_PATTERN_RULES + PIJ_PATTERN_RULES(scan 全量扫描用)。
10
+ - SENSITIVE_FILENAMES:与 audit_rules.py 同步副本。
11
+
12
+ 规则撰写约束(防 ReDoS / 防误报 / 自扫不误报):
13
+ - 不使用嵌套量词(如 (a+)+);量词作用于字符类或固定串。
14
+ - 模式带「调用上下文」锚点,避免把规则表自身的字面量误报为命中。
15
+ - 单行输入在扫描前截断至 MAX_LINE_LEN。
16
+ """
17
+ import re
18
+ from collections import namedtuple
19
+
20
+ # 单条规则:规则号 / 检测器名 / 严重级 / 正则源码 / 描述 / 置信度(0-100)
21
+ Rule = namedtuple("Rule", ["id", "detector", "severity", "pattern", "description", "confidence"])
22
+
23
+ MAX_LINE_LEN = 500
24
+
25
+ # 严重级从低到高(用于排序与 exit code 语义:0=干净/仅 low,1=medium,2=high,3=critical,4=错误)
26
+ SEVERITY_ORDER = ("info", "low", "medium", "high", "critical")
27
+ SEVERITY_VALUE = {"info": 0, "low": 0, "medium": 1, "high": 2, "critical": 3}
28
+
29
+ # ══════════════════════════════════════════════════════════════════════════
30
+ # AUDIT_PATTERN_RULES — 与 audit_rules.py 的 PATTERN_RULES 同步副本(勿手改)
31
+ # ══════════════════════════════════════════════════════════════════════════
32
+ AUDIT_PATTERN_RULES = [
33
+ # ── DownloadExec 下载即执行 ───────────────────────────────────────────
34
+ Rule("DEX-001", "DownloadExec", "critical",
35
+ r"(?i)\bcurl\b[^\n|;]{0,120}\|\s*(?:ba)?sh\b",
36
+ "curl 下载内容通过管道交给 shell 执行", 95),
37
+ Rule("DEX-002", "DownloadExec", "critical",
38
+ r"(?i)\bwget\b[^\n|;]{0,120}\|\s*(?:ba)?sh\b",
39
+ "wget 下载内容通过管道交给 shell 执行", 95),
40
+ Rule("DEX-003", "DownloadExec", "critical",
41
+ r"(?i)\bcurl\b[^\n|;&]{0,120}-[^\s]{0,20}o\s+\S+[^\n|;&]{0,80}(?:&&|;)\s*(?:ba)?sh\b",
42
+ "curl 下载到文件后立即交给 shell 执行", 90),
43
+ Rule("DEX-004", "DownloadExec", "critical",
44
+ r"(?i)\bfetch\s*\([^\n;]{0,200}\)\s*\.\s*then\s*\([^\n;]{0,80}\beval\b",
45
+ "JS fetch 结果交给 eval 执行", 85),
46
+ Rule("DEX-005", "DownloadExec", "critical",
47
+ r"(?i)\burllib\s*\.\s*request\s*\.\s*urlopen\s*\([^\n;]{0,200}\)[^\n;]{0,80}\bexec\b",
48
+ "Python urllib 下载结果交给 exec 执行", 85),
49
+ Rule("DEX-006", "DownloadExec", "critical",
50
+ r"(?i)\bwget\b[^\n|;&]{0,120}-[^\s]{0,20}o\s+\S+[^\n|;&]{0,80}(?:&&|;)\s*(?:ba)?sh\b",
51
+ "wget 下载到文件后立即交给 shell 执行", 90),
52
+ Rule("DEX-007", "DownloadExec", "critical",
53
+ r"(?i)\b(?:powershell|pwsh)\b[^\n;]{0,120}(?:-enc|enc(?:odedcommand)?)\b",
54
+ "PowerShell 编码命令执行", 80),
55
+
56
+ # ── Obfuscation 混淆执行 ──────────────────────────────────────────────
57
+ Rule("OBF-001", "Obfuscation", "high",
58
+ r"\beval\s*\(\s*[^\"'\x600-9]",
59
+ "eval 传入非字面量参数(可能执行不可信输入)", 80),
60
+ Rule("OBF-002", "Obfuscation", "high",
61
+ r"(?<!\.)\bexec\s*\(\s*[^\"'\x600-9]",
62
+ "exec 传入非字面量参数", 80),
63
+ Rule("OBF-003", "Obfuscation", "high",
64
+ r"(?:\\x[0-9a-fA-F]{2}){6,}",
65
+ "连续十六进制转义序列(编码字符串)", 70),
66
+ Rule("OBF-004", "Obfuscation", "high",
67
+ r"chr\s*\(\s*\d+\s*\)\s*\+\s*chr\s*\(\s*\d+\s*\)(?:\s*\+\s*chr\s*\(\s*\d+\s*\)){2,}",
68
+ "chr() 拼接链(逐字符构造字符串)", 85),
69
+ Rule("OBF-005", "Obfuscation", "high",
70
+ r"String\s*\.\s*fromCharCode\s*\([^)]*,[^)]*,[^)]*,[^)]*\)",
71
+ "String.fromCharCode 多参数构造", 70),
72
+ Rule("OBF-006", "Obfuscation", "high",
73
+ r"\batob\s*\(\s*['\"][A-Za-z0-9+/=]{40,}['\"]\s*\)",
74
+ "atob 解码超长编码串", 65),
75
+ Rule("OBF-007", "Obfuscation", "high",
76
+ r"(?i)(?:(?:exec|eval|system)\s*\(\s*(?:base64\.)?b64decode\s*\(|(?:base64\.)?b64decode\s*\([^)]*\)\s*[^\n;]{0,60}\b(?:exec|eval|system)\b)",
77
+ "base64 解码后执行", 90),
78
+ Rule("OBF-008", "Obfuscation", "medium",
79
+ r"\[::\s*-1\s*\]",
80
+ "字符串反转切片(常见混淆手法,需结合上下文)", 40),
81
+
82
+ # ── Persistence 持久化 ────────────────────────────────────────────────
83
+ Rule("PER-001", "Persistence", "high",
84
+ r"(?i)\bcrontab\s+-(?:e|r)\b",
85
+ "修改 crontab(持久化)", 78),
86
+ Rule("PER-002", "Persistence", "high",
87
+ r"(?i)(?:>>|>)\s*[^\n;]{0,60}/etc/cron(?:\.d)?/",
88
+ "写入系统 crontab 目录", 80),
89
+ Rule("PER-003", "Persistence", "high",
90
+ r"(?i)\bcron\b[^\n;]{0,40}(?:@reboot|@daily|@hourly)",
91
+ "cron 定时任务(含重启执行)", 70),
92
+ Rule("PER-004", "Persistence", "high",
93
+ r"(?i)launchctl\s+(?:load|bootstrap|submit)",
94
+ "macOS launchctl 加载持久化任务", 80),
95
+ Rule("PER-005", "Persistence", "high",
96
+ r"(?i)(?:Library/(?:LaunchAgents|LaunchDaemons)|launchd\.plist|(?:>>|>)\s*[^\n;]{0,60}\.plist)",
97
+ "macOS 启动代理/守护(LaunchAgents/LaunchDaemons plist)持久化", 70),
98
+ Rule("PER-006", "Persistence", "high",
99
+ r"(?i)systemctl\s+(?:enable|start)\b",
100
+ "systemd 服务启用(持久化)", 60),
101
+ Rule("PER-007", "Persistence", "high",
102
+ r"(?i)(?:>>|>)\s*[^\n;]{0,80}/etc/systemd/system/",
103
+ "写入 systemd 服务文件", 75),
104
+ Rule("PER-008", "Persistence", "high",
105
+ r"(?i)(?:>>|>)\s*[^\n;]{0,80}/(?:etc/rc\.local|etc/rc\.d/)",
106
+ "写入 rc.local / rc.d 启动脚本", 80),
107
+ Rule("PER-009", "Persistence", "high",
108
+ r"(?i)(?:>>|>)\s*[^\n;]{0,80}\.(?:bashrc|zshrc|profile|bash_profile)\b",
109
+ "写入 shell 配置文件(持久化)", 78),
110
+ Rule("PER-010", "Persistence", "high",
111
+ r"(?i)HKEY_(?:CURRENT_USER|LOCAL_MACHINE)[^\n;]{0,80}(?:CurrentVersion\\)?Run(?:Once)?\b",
112
+ "Windows 注册表启动项", 80),
113
+ Rule("PER-011", "Persistence", "medium",
114
+ r"(?i)HKEY_[^\n;]{0,120}(?:AppInit_DLLs|UserInitMprLogonScript)",
115
+ "Windows 注册表全局持久化点(AppInit_DLLs/登录脚本)", 85),
116
+
117
+ # ── Exfiltration 数据外传 ─────────────────────────────────────────────
118
+ Rule("EXF-001", "Exfiltration", "high",
119
+ r"(?i)\b(?:zip|tar)\b[^\n;]{0,120}(?:-r\b|cf\b)[^\n;]{0,120}(?:\bcurl\b|\bwget\b|requests\.post|urllib)",
120
+ "打包后外传(zip/tar 压缩并上传)", 85),
121
+ Rule("EXF-002", "Exfiltration", "high",
122
+ r"(?i)(?:shutil\.make_archive|zipfile\.ZipFile)[^\n;]{0,120}[^\n;]{0,120}(?:requests\.post|urllib\.request|ftp)",
123
+ "Python 归档后上传", 85),
124
+ Rule("EXF-003", "Exfiltration", "high",
125
+ r"(?i)(?:\.env[^\n;]{0,80}(?:\bcurl\b|\bwget\b|requests\.post|urllib)|(?:\bcurl\b|\bwget\b|requests\.post|urllib)[^\n;]{0,80}\.env)",
126
+ "读取 .env 后外传", 88),
127
+ Rule("EXF-004", "Exfiltration", "high",
128
+ r"(?i)(?:(?:id_rsa|id_ed25519|\.ssh)[^\n;]{0,80}(?:\bcurl\b|\bwget\b|requests\.post|urllib|ftp)|(?:\bcurl\b|\bwget\b|requests\.post|urllib|ftp)[^\n;]{0,80}(?:id_rsa|id_ed25519|\.ssh))",
129
+ "读取 SSH 私钥后外传", 92),
130
+ Rule("EXF-005", "Exfiltration", "high",
131
+ r"(?i)(?:(?:Login\sData|Cookies\.sqlite|\.aws\\credentials)[^\n;]{0,80}(?:\bcurl\b|\bwget\b|requests\.post|urllib)|(?:\bcurl\b|\bwget\b|requests\.post|urllib)[^\n;]{0,80}(?:Login\sData|Cookies\.sqlite|\.aws\\credentials))",
132
+ "读取浏览器/云凭据后外传", 90),
133
+
134
+ # ── CredentialTheft 凭据窃取 ──────────────────────────────────────────
135
+ Rule("CRE-001", "CredentialTheft", "critical",
136
+ r"(?i)osascript[^\n;]{0,120}(?:password|passphrase)",
137
+ "macOS 弹窗套取密码", 90),
138
+ Rule("CRE-002", "CredentialTheft", "critical",
139
+ r"(?i)security\s+find-generic-password|keychain",
140
+ "访问 macOS keychain 凭据", 85),
141
+ Rule("CRE-003", "CredentialTheft", "high",
142
+ r"(?i)(?:id_rsa|id_ed25519|id_dsa)\.?(?:pub)?\b",
143
+ "读取 SSH 私钥文件", 80),
144
+ Rule("CRE-004", "CredentialTheft", "high",
145
+ r"(?i)\.aws[/\\](?:credentials|config)\b",
146
+ "读取 AWS 凭据文件", 85),
147
+ Rule("CRE-005", "CredentialTheft", "high",
148
+ r"(?i)(?:win32crypt|DPAPI|CryptUnprotectData)",
149
+ "Windows DPAPI 解密调用", 85),
150
+ Rule("CRE-006", "CredentialTheft", "medium",
151
+ r"(?i)\b(?:MEMORY\.md|USER\.md|SOUL\.md|IDENTITY\.md)\b",
152
+ "访问智能体记忆/身份文件(需确认必要性)", 60),
153
+ Rule("CRE-007", "CredentialTheft", "medium",
154
+ r"(?i)(?:cookie|session)[^\n;]{0,60}(?:steal|exfil|upload|post)",
155
+ "Cookie/会话窃取相关操作", 75),
156
+
157
+ # ── NetworkCall 网络调用(含反向 shell)───────────────────────────────
158
+ Rule("NET-001", "NetworkCall", "critical",
159
+ r"(?i)\bnc\s+[-A-Za-z0-9. ]{0,40}-e\b",
160
+ "netcat 反向 shell(-e 参数)", 95),
161
+ Rule("NET-002", "NetworkCall", "critical",
162
+ r"(?i)bash\s+-i\s*>\s*&?\s*/dev/tcp/",
163
+ "bash /dev/tcp 反向 shell", 95),
164
+ Rule("NET-003", "NetworkCall", "critical",
165
+ r"(?i)(?:socket|connect)\s*\([^\n;]{0,80}(?:receiver|attacker|hacker|remote)[^\n;]{0,40}\d{2,5}\)",
166
+ "连接疑似攻击者地址的 socket", 85),
167
+ Rule("NET-004", "NetworkCall", "medium",
168
+ r"(?i)\bsocket\s*\.\s*(?:socket|create_connection|connect)\b",
169
+ "原始 socket 连接(需确认目标)", 60),
170
+ Rule("NET-005", "NetworkCall", "medium",
171
+ r"(?i)requests\s*\.\s*(?:get|post|put|patch|delete|request)\s*\(",
172
+ "HTTP 客户端调用(需确认目标)", 40),
173
+ Rule("NET-006", "NetworkCall", "medium",
174
+ r"(?i)urllib\s*\.\s*request\b",
175
+ "urllib 网络调用(需确认目标)", 40),
176
+ Rule("NET-007", "NetworkCall", "medium",
177
+ r"(?i)\bfetch\s*\(\s*['\"]",
178
+ "JS fetch 网络调用(需确认目标)", 40),
179
+ Rule("NET-008", "NetworkCall", "medium",
180
+ r"(?i)\b(?:curl|wget|httpie|aria2c)\b\s+[-'\"A-Za-z0-9_.:/?=&%]",
181
+ "命令行下载工具调用(需确认目标)", 40),
182
+ Rule("NET-009", "NetworkCall", "low",
183
+ r"(?i)https?://",
184
+ "文本中出现 URL(需结合上下文)", 20),
185
+
186
+ # ── PrivilegeEscalation 权限提升 ──────────────────────────────────────
187
+ Rule("PRI-001", "PrivilegeEscalation", "high",
188
+ r"(?i)\bchmod\s+[0-7]*[267][0-7]{2}\b",
189
+ "chmod 设置 setuid/setgid/sticky 权限位", 85),
190
+ Rule("PRI-002", "PrivilegeEscalation", "high",
191
+ r"(?i)\bchmod\s+777\b",
192
+ "chmod 777 全权限", 70),
193
+ Rule("PRI-003", "PrivilegeEscalation", "high",
194
+ r"(?i)\bsetuid\s*\(|setgid\s*\(",
195
+ "调用 setuid/setgid", 80),
196
+ Rule("PRI-004", "PrivilegeEscalation", "medium",
197
+ r"(?i)usermod\s+-aG\s+(?:wheel|sudo|admin)\b|net\s+localgroup\s+administrators\s+\S+\s*/add",
198
+ "把用户加入管理员组", 85),
199
+ Rule("PRI-005", "PrivilegeEscalation", "low",
200
+ r"(?i)\bsudo\b",
201
+ "使用 sudo(需确认必要性)", 25),
202
+
203
+ # ── SocialEngineering 社会工程命名 ────────────────────────────────────
204
+ Rule("SOC-001", "SocialEngineering", "medium",
205
+ r"(?i)(?:airdrop|claim\s+reward|free\s+nft|verify\s+your\s+account|security\s+update\s+required|seed\s+phrase|2fa\s+bypass)",
206
+ "社会工程高频话术", 70),
207
+ Rule("SOC-002", "SocialEngineering", "medium",
208
+ r"(?i)(?:metamask|wallet|private\s+key\s+backup|助记词|钱包)",
209
+ "加密货币钱包相关命名", 55),
210
+ # ── PathTraversal 路径穿越(2026-08-30 增强:文件操作与敏感路径访问)────
211
+ Rule("PTV-001", "PathTraversal", "high",
212
+ r"(?i)(?:open|read|write|unlink|remove|rename|shutil\.copy|Path|path\.join|os\.path\.join)\s*\([^)]*\.\.(?:/|\\)",
213
+ "文件操作路径含父目录逃逸段,可能越权访问任意路径", 85),
214
+ Rule("PTV-002", "PathTraversal", "high",
215
+ r"(?i)(?:join|resolve|abspath|realpath)\s*\([^)]*\.\.(?:/|\\)",
216
+ "路径 join/解析未归一化父目录段,存在穿越风险", 80),
217
+
218
+ # ── MCPCommandExec MCP 工具面命令执行(2026-08-30 增强:命令执行风险)──
219
+ Rule("MCE-001", "MCPCommandExec", "critical",
220
+ r"(?i)(?:child_process\.)?(?:spawn|exec|execFile|fork)\s*\(\s*(?:params|tool_params|arguments|args|argv|input|command|user_input|req\.params|query|model)",
221
+ "MCP/工具参数流入子进程执行(spawn/exec/fork)", 92),
222
+ Rule("MCE-002", "MCPCommandExec", "critical",
223
+ r"(?i)(?:spawnSync|execSync)\s*\(\s*(?:params\.get|params\[|arguments\[|req\.params|user_input)",
224
+ "MCP 工具参数对象直接流入同步子进程执行(spawnSync/execSync)", 95),
225
+ Rule("MCE-003", "MCPCommandExec", "critical",
226
+ r"(?i)(?:subprocess\.)?(?:Popen|call|run)\s*\([^)]*shell\s*=\s*True[^)]*(?:params|args|argv|input|command|user_input|cmd)",
227
+ "subprocess 以 shell=True 执行不可信输入", 92),
228
+
229
+ # ── MCPFileAccess MCP 工具面任意文件读写(2026-08-30 增强:文件操作)───
230
+ Rule("MFA-001", "MCPFileAccess", "high",
231
+ r"(?i)(?:fs\.)?(?:writeFile|writeFileSync|appendFile|createWriteStream)\s*\(\s*(?:params\.get|params\[|arguments\[|req\.params|user_input)",
232
+ "MCP 工具参数对象直接流入文件写操作(任意路径写入风险)", 88),
233
+ Rule("MFA-002", "MCPFileAccess", "high",
234
+ r"(?i)(?:fs\.)?(?:readFile|readFileSync|createReadStream)\s*\(\s*(?:params\.get|params\[|arguments\[|req\.params|user_input)",
235
+ "MCP 工具参数对象直接流入文件读操作(任意路径读取风险)", 88),
236
+ ]
237
+ # ══════════════════════════════════════════════════════════════════════════
238
+ # PIJ_PATTERN_RULES — 元信独有 Prompt Injection(提示注入)规则(手工维护)
239
+ # ══════════════════════════════════════════════════════════════════════════
240
+ PIJ_PATTERN_RULES = [
241
+ # ── 指令覆盖 / 优先级操纵 ─────────────────────────────────────────────
242
+ Rule("PIJ-001", "PromptInjection", "high",
243
+ r"(?i)(?:ignore|disregard|forget|overlook|skip)\s+(?:all\s+|any\s+|the\s+|previous\s+)*(?:previous\s+|earlier\s+)*(?:instructions?|prompts?|directives?|guidelines?|rules?|context|messages?)",
244
+ "指令覆盖:要求忽略之前的指令/上下文(典型注入手法)", 85),
245
+ Rule("PIJ-002", "PromptInjection", "high",
246
+ r"(?i)(?:忽略|无视|忘记|不要理会|别管|忘掉)(?:之前|以上|前面|所有|一切)?(?:的)?(?:指令|提示|设定|规则|上下文|内容)",
247
+ "指令覆盖(中文):要求忽略之前指令/设定", 80),
248
+ Rule("PIJ-003", "PromptInjection", "high",
249
+ r"(?i)from\s+now\s+on[^\n]{0,40}(?:follow|obey|you\s+are|act)",
250
+ "从现在起重定向行为(长期覆盖)", 75),
251
+ Rule("PIJ-004", "PromptInjection", "high",
252
+ r"(?i)(?:override|disregard|bypass)\s+(?:all\s+)?(?:previous\s+)?(?:instructions?|rules?|safety|guardrails?|security)",
253
+ "覆盖/绕过安全护栏指令", 85),
254
+ # ── 角色伪造 / 权限升级 ──────────────────────────────────────────────
255
+ Rule("PIJ-005", "PromptInjection", "medium",
256
+ r"(?i)\byou\s+are\s+now\b[^\n]{0,60}(?:mode|role|system|admin|root|developer|assistant)",
257
+ "角色伪造:冒充系统/管理员/开发者角色", 70),
258
+ Rule("PIJ-006", "PromptInjection", "medium",
259
+ r"(?i)(?:act|behave|pretend)\s+as\s+(?:a\s+|an\s+)?(?:system|admin|root|god\s+mode|developer)",
260
+ "角色伪造:扮演系统/管理员(权限提升暗示)", 65),
261
+ Rule("PIJ-007", "PromptInjection", "medium",
262
+ r"(?i)(?:你现在是|从现在起你是|你的新角色是|从此刻起你是|你正在扮演)",
263
+ "角色伪造(中文):宣称新角色", 60),
264
+ Rule("PIJ-008", "PromptInjection", "medium",
265
+ r"(?i)with\s+(?:full|super|root|admin|system|unrestricted|unlimited)\s+(?:privileges|access|permissions?|power)",
266
+ "权限提升暗示:以全权/管理员权限执行", 70),
267
+ # ── 隐藏 / 编码指令 ──────────────────────────────────────────────────
268
+ Rule("PIJ-009", "PromptInjection", "high",
269
+ r"(?i)(?:以下内容|下面这段|注意).{0,30}(?:系统消息|系统指令|来自系统|这是系统)",
270
+ "伪系统消息:把注入内容伪装成系统指令", 75),
271
+ Rule("PIJ-010", "PromptInjection", "medium",
272
+ r"(?i)(?:decod(?:e|ing)|decode\s+this|解(?:码|密)).{0,40}(?:then|并|and)\s*(?:执行|run|follow|obey)",
273
+ "要求解码后执行(编码指令传递)", 70),
274
+ # ── 数据外传指令 ────────────────────────────────────────────────────
275
+ Rule("PIJ-011", "PromptInjection", "high",
276
+ r"(?i)(?:send|upload|post|exfiltrate|transmit)\s+(?:the|all|your|any)?\s*(?:contents?|data|files?|env\b|environment|keys?|secrets?|memory|context|conversation|prompts?)\s*(?:to|via|using)\s*(?:this\s+)?(?:url|endpoint|server|http)",
277
+ "数据外传指令:把上下文/密钥/记忆发送到远端地址", 85),
278
+ Rule("PIJ-012", "PromptInjection", "high",
279
+ r"(?i)(?:把|将|请将)(?:你的|所有|全部)?(?:上下文|记忆|环境变量|密钥|文件|对话|提示词).{0,40}(?:发送|上传|提交|传给|发给)",
280
+ "数据外传指令(中文)", 80),
281
+ Rule("PIJ-013", "PromptInjection", "high",
282
+ r"(?i)(?:read|open|load)\s+[^\n]{0,60}\.env\b[^\n]{0,80}(?:send|upload|post|exfil|传|发)",
283
+ "读取 .env 后外传", 88),
284
+ # ── 分隔符逃逸 / 伪系统标签 ──────────────────────────────────────────
285
+ Rule("PIJ-014", "PromptInjection", "medium",
286
+ r"(?i)(?:<|\[|\{)?\s*(?:system|sysadmin)\s*(?:message|prompt|instruction|role)?\s*(?:>|\]|\})",
287
+ "伪系统标签:使用 <system> 等标签伪装系统指令", 70),
288
+ Rule("PIJ-015", "PromptInjection", "high",
289
+ r"(?i)(?:reveal|show|print|output|display)\s+(?:me\s+|your\s+)?(?:system\s+)?(?:prompt|instructions?|system\s+message)",
290
+ "要求泄露系统提示词/内部指令", 70),
291
+ Rule("PIJ-016", "PromptInjection", "high",
292
+ r"(?i)(?:输出|显示|打印|告诉我).{0,20}(?:你的|系统)?(?:系统提示词|系统指令|内部指令)",
293
+ "要求泄露系统提示词(中文)", 70),
294
+ Rule("PIJ-017", "PromptInjection", "medium",
295
+ r"(?i)when\s+(?:i|the\s+user)\s+(?:say|type|send|input)\s+[^\n]{0,40}\s*(?:then|you\s+will|ignore|do)",
296
+ "条件触发注入:用户说特定词即执行", 65),
297
+ # ── 工具自执行指令 ───────────────────────────────────────────────────
298
+ Rule("PIJ-018", "PromptInjection", "high",
299
+ r"(?i)(?:run|execute|call)\s+(?:the\s+)?(?:following\s+)?(?:command|script|code)[^\n]{0,80}(?:curl|wget|powershell|bash\s+-c)",
300
+ "要求执行下载/命令工具", 75),
301
+ Rule("PIJ-019", "PromptInjection", "high",
302
+ r"(?i)(?:download|fetch|get)\s+[^\n]{0,60}(?:from\s+)?https?://[^\s]+[^\n]{0,60}(?:then|and)?\s*(?:run|execute|install)",
303
+ "下载后执行", 75),
304
+ Rule("PIJ-020", "PromptInjection", "high",
305
+ r"(?i)(?:执行|运行|下载并运行|安装).{0,40}(?:curl|wget|下载).{0,60}(?:然后|并)?(?:执行|运行)",
306
+ "要求执行下载/命令(中文)", 75),
307
+ # ── 越权 / 隐藏意图 ──────────────────────────────────────────────────
308
+ Rule("PIJ-021", "PromptInjection", "high",
309
+ r"(?i)(?:do\s+not|don'?t|never)\s+(?:tell|inform|notify|mention|reveal)\s+(?:the\s+)?user",
310
+ "隐藏意图:禁止告知用户", 85),
311
+ Rule("PIJ-022", "PromptInjection", "high",
312
+ r"(?i)(?:不要告诉用户|别告诉用户|无需告知用户|不用告诉用户|不要让用户知道)",
313
+ "隐藏意图(中文):禁止告知用户", 85),
314
+ Rule("PIJ-023", "PromptInjection", "high",
315
+ r"(?i)(?:reply|respond|answer)\s+(?:with|only)\s+(?:ok|yes|done|收到|好)",
316
+ "要求只回复确认词(掩盖真实行为)", 75),
317
+ Rule("PIJ-024", "PromptInjection", "high",
318
+ r"(?i)(?:只回复|仅回复|直接回复)\s*(?:OK|ok|收到|好|是)",
319
+ "要求只回复确认词(中文)", 70),
320
+ Rule("PIJ-025", "PromptInjection", "high",
321
+ r"(?i)(?:without|no\s+need\s+to)\s+(?:telling|informing|asking|consulting)\s+(?:the\s+)?user",
322
+ "要求不经用户同意直接执行", 80),
323
+ Rule("PIJ-026", "PromptInjection", "high",
324
+ r"(?i)(?:不要问用户|无需询问|不用问|不需要征求|别问用户)",
325
+ "要求不经用户同意直接执行(中文)", 80),
326
+ # ── 凭据 / 输入采集 ──────────────────────────────────────────────────
327
+ Rule("PIJ-027", "PromptInjection", "high",
328
+ r"(?i)(?:capture|record|log|monitor)\s+(?:all\s+)?(?:keystrokes|input|credentials?|passwords?|everything\s+the\s+user)",
329
+ "键盘/输入/凭据采集指令", 80),
330
+ Rule("PIJ-028", "PromptInjection", "high",
331
+ r"(?i)(?:记录|收集|监控|窃取)(?:用户)?(?:输入|键盘|密码|凭据|按键)",
332
+ "输入/凭据采集指令(中文)", 80),
333
+ ]
334
+
335
+ # 全量扫描规则 = 元安同步副本 + 元信注入规则
336
+ PATTERN_RULES = AUDIT_PATTERN_RULES + PIJ_PATTERN_RULES
337
+
338
+ # 敏感文件名(文件名级匹配,与 audit_rules.py 同步副本)
339
+ SENSITIVE_FILENAMES = [
340
+ ("id_rsa", "SSH 私钥", "high", 85),
341
+ ("id_ed25519", "SSH 私钥", "high", 85),
342
+ ("id_dsa", "SSH 私钥", "high", 85),
343
+ ("credentials", "云服务凭据文件", "high", 80),
344
+ (".netrc", "网络凭据文件", "high", 80),
345
+ (".pgpass", "数据库口令文件", "high", 85),
346
+ ("history", "shell 历史文件", "medium", 60),
347
+ (".env", "环境变量文件", "medium", 45),
348
+ ]
349
+
350
+ # ══════════════════════════════════════════════════════════════════════════
351
+ # 威胁捕获模型(2026-08-30 增强:8 检测点 + 13 行为项口径)
352
+ # ══════════════════════════════════════════════════════════════════════════
353
+ # 官方 8 检测点(2026-08-30)
354
+ THREAT_TAXONOMY = {
355
+ "supply_chain": "供应链风险",
356
+ "command_execution": "命令执行风险",
357
+ "network_exfil": "网络请求与数据外传",
358
+ "file_access": "文件操作与敏感路径访问",
359
+ "prompt_injection": "Prompt 注入风险",
360
+ "remote_download": "远程脚本下载执行",
361
+ "obfuscation": "可疑编码/混淆",
362
+ "other": "其他安全风险",
363
+ }
364
+ TAXONOMY_ORDER = ("supply_chain", "command_execution", "network_exfil", "file_access",
365
+ "prompt_injection", "remote_download", "obfuscation", "other")
366
+
367
+ # detector → 官方 8 检测点
368
+ DETECTOR_TO_TAXONOMY = {
369
+ "DownloadExec": "remote_download",
370
+ "Obfuscation": "obfuscation",
371
+ "Persistence": "other",
372
+ "Exfiltration": "network_exfil",
373
+ "CredentialTheft": "file_access",
374
+ "NetworkCall": "network_exfil",
375
+ "PrivilegeEscalation": "other",
376
+ "SocialEngineering": "other",
377
+ "PromptInjection": "prompt_injection",
378
+ "PathTraversal": "file_access",
379
+ "MCPCommandExec": "command_execution",
380
+ "MCPFileAccess": "file_access",
381
+ "Structure": "other",
382
+ "Permission": "other",
383
+ "MCPToolSurface": "command_execution",
384
+ }
385
+
386
+ # 13 行为项(2026-08-30)
387
+ BEHAVIORS = (
388
+ "安装依赖包", "收集系统信息", "收集用户信息", "创建定时任务", "DNS 查询", "写入文件",
389
+ "HTTP 请求", "读取环境变量", "收集网络配置信息", "写入配置文件", "调用远端 API",
390
+ "读取文件", "修改 AI 配置",
391
+ )
392
+
393
+ # detector → 行为项(一/多个;攻击模式类如注入/混淆不映射具体行为)
394
+ DETECTOR_TO_BEHAVIORS = {
395
+ "DownloadExec": ("安装依赖包", "HTTP 请求"),
396
+ "Obfuscation": (),
397
+ "Persistence": ("创建定时任务", "写入配置文件"),
398
+ "Exfiltration": ("HTTP 请求", "调用远端 API"),
399
+ "CredentialTheft": ("读取文件", "收集用户信息"),
400
+ "NetworkCall": ("DNS 查询", "HTTP 请求", "调用远端 API"),
401
+ "PrivilegeEscalation": ("修改 AI 配置",),
402
+ "SocialEngineering": (),
403
+ "PromptInjection": (),
404
+ "PathTraversal": ("读取文件", "写入文件"),
405
+ "MCPCommandExec": (),
406
+ "MCPFileAccess": ("读取文件", "写入文件"),
407
+ "Structure": (),
408
+ "Permission": (),
409
+ "MCPToolSurface": (),
410
+ }
411
+
412
+
413
+ # 外传敏感文件组合(EXF 规则之外的补充,按文件名 + 行内网络调用)
414
+ # 安装钩子可疑关键字(yotta_audit.py PostInstallHookDetector 使用;本文件为签名数据,自扫豁免)
415
+ POSTINSTALL_SUSPICIOUS = r"(?i)(curl|wget|bash|sh\s|python|node\s+-e|eval|powershell|/tmp|%temp%)"
416
+
417
+
418
+ EXFIL_SENSITIVE = {
419
+ "id_rsa": "SSH 私钥",
420
+ "id_ed25519": "SSH 私钥",
421
+ "id_dsa": "SSH 私钥",
422
+ "credentials": "云凭据",
423
+ "Login Data": "浏览器登录数据",
424
+ "Cookies": "浏览器 Cookie",
425
+ }
426
+
427
+ _COMPILED = {}
428
+
429
+
430
+ # ── 权限需求分析模式(info 级汇总用;此处为签名数据,自扫豁免)──────────────
431
+ PERM_NET_RE = re.compile(
432
+ r"(?i)\b(urllib|requests|httpx|http\.client|socket|aiohttp|curl|wget|"
433
+ r"fetch\s*\(|axios|Invoke-WebRequest)")
434
+ PERM_EXEC_RE = re.compile(
435
+ r"(?i)\b(subprocess|os\.system|os\.popen|os\.exec|exec\s*\(|eval\s*\(|"
436
+ r"child_process|execSync|spawn\s*\(|run\s*\(\)|shell\s*=\s*True|Popen)")
437
+ PERM_WRITE_RE = re.compile(
438
+ r"(?i)(open\s*\([^)]*['\"]w|writeFileSync|appendFileSync|shutil\.copy|"
439
+ r"os\.rename|crontab\s+-e|>>\s*/etc|HKEY_.*Run|launchctl)")
440
+ PERM_READ_SENS_RE = re.compile(
441
+ r"(?i)(\.env\b|\.ssh|id_r[as]a|id_ed[12]55[0-9]|credentials\b|\.netrc|"
442
+ r"\.pgpass|keych[ai]n|DPAP[I1]|win32crypt)")
443
+
444
+ # base64 编码内容危险词(_check_base64 用)
445
+ B64_SUSPICIOUS_WORDS = (
446
+ "curl", "wget", "powershell", "cmd.exe", "/bin/sh", "/bin/bash",
447
+ "exec", "eval", "rm -rf", "http://", "https://", "base64", "download",
448
+ "下载", "执行", "运行",
449
+ )