Deep Dive | src/tools/BashTool/bashPermissions.ts 2621 行 — Bash 权限规则引擎¶
重要性:⭐⭐⭐(Bash 工具权限核心——规则匹配、classifier 集成、speculative 预检) 真实位置:
src/tools/BashTool/bashPermissions.ts(2621 行) 角色:决定Bash(...)工具调用是 allow / deny / ask —— 规则匹配 + sandbox 检查 + LLM classifier 关联:topics/deep-dive-bash-parser.md、topics/deep-dive-bash-ast.md、topics/deep-dive-bash-security.md
1. 文件全景¶
bashPermissions.ts (2621 行)
│
├── 行 1-160 :imports + DEPRECATED aliases + 常量
│ ├── bashCommandIsSafeAsync_DEPRECATED
│ ├── MAX_SUBCOMMANDS_FOR_SECURITY_CHECK (50)
│ └── MAX_SUGGESTED_RULES_FOR_COMPOUND (5)
│
├── 行 117-260 :prefix 提取
│ ├── logClassifierResultForAnts (行 117)
│ ├── getSimpleCommandPrefix (行 161, ~35 行)
│ ├── BARE_SHELL_PREFIXES (行 196)
│ └── getFirstWordPrefix (行 243, ~25 行)
│
├── 行 266-370 :suggestion
│ ├── suggestionForExactCommand (行 266, ~40 行)
│ ├── extractPrefixBeforeHeredoc (行 307, ~32 行)
│ ├── suggestionForPrefix (行 339)
│ └── permissionRuleExtractPrefix (行 347)
│
├── 行 353-510 :wildcard + rule
│ ├── matchWildcardPattern (行 353, ~10 行)
│ ├── bashPermissionRule (行 364, ~15 行)
│ ├── SAFE_ENV_VARS (行 378, ~70 行白名单)
│ └── ANT_ONLY_SAFE_ENV_VARS (行 447, ~60 行)
│
├── 行 508-680 :strip helpers
│ ├── stripCommentLines (行 508, ~16 行)
│ ├── stripSafeWrappers (行 524, ~95 行)
│ ├── skipTimeoutFlags (行 633, ~45 行)
│ └── stripWrappersFromArgv (行 678, ~30 行)
│
├── 行 708-780 :env vars
│ ├── BINARY_HIJACK_VARS (LD_/DYLD_/PATH)
│ └── stripAllLeadingEnvVars (行 733, ~45 行)
│
├── 行 778-940 :rule filter
│ ├── filterRulesByContentsMatchingInput (行 778, ~160 行)
│ └── matchingRulesForInput (行 937, ~55 行)
│
├── 行 991-1270:主检查函数
│ ├── bashToolCheckExactMatchPermission (行 991, ~60 行)
│ ├── bashToolCheckPermission (行 1050, ~130 行)
│ └── checkCommandAndSuggestRules (行 1183, ~85 行)
│
├── 行 1270-1459:sandbox + 拒绝
│ ├── checkSandboxAutoAllow (行 1270, ~95 行)
│ ├── filterCdCwdSubcommands (行 1367, ~25 行)
│ ├── checkEarlyExitDeny (行 1391, ~40 行)
│ └── checkSemanticsDeny (行 1431, ~30 行)
│
├── 行 1459-1663:speculative classifier
│ ├── buildPendingClassifierCheck (行 1459, ~25 行)
│ ├── speculativeChecks (Map)
│ ├── peekSpeculativeClassifierCheck (行 1491)
│ ├── startSpeculativeClassifierCheck (行 1497, ~35 行)
│ ├── consumeSpeculativeClassifierCheck (行 1533)
│ ├── clearSpeculativeChecks (行 1543)
│ ├── awaitClassifierAutoApproval (行 1555, ~35 行)
│ └── executeAsyncClassifierCheck (行 1605, ~60 行)
│
├── 行 1663-2567:**bashToolHasPermission (行 1663, ~900 行核心)** — 主入口
│
└── 行 2567-2621:normalized check
├── isNormalizedGitCommand (行 2567, ~35 行)
├── isNormalizedCdCommand (行 2603, ~15 行)
└── commandHasAnyCd (行 2617)
2. 2 个 DEPRECATED Alias¶
const bashCommandIsSafeAsync = bashCommandIsSafeAsync_DEPRECATED
const splitCommand = splitCommand_DEPRECATED
2 个 alias——保持向后兼容(旧 API 不直接用,但 import 不破)。
3. 2 个 MAX 常量¶
2 个上限: - 50 个 subcommands 后停止 security check - 5 个 suggested rules(避免一次问太多)
4. Prefix 提取(4 个函数)¶
getSimpleCommandPrefix(command) // 简单命令前缀 (git, npm, ...)
getFirstWordPrefix(command) // 第一个 word 的前缀
suggestionForExactCommand(cmd) // 精确命令 → rules
extractPrefixBeforeHeredoc(cmd) // heredoc 前的部分
suggestionForPrefix(prefix) // 前缀 → rules
5 个 prefix 函数——决定匹配规则的范围。
5. bashPermissionRule — 规则定义¶
单一规则结构——Bash(git:*) / Bash(rm:*) 等。
6. SAFE_ENV_VARS + ANT_ONLY_SAFE_ENV_VARS — 环境变量白名单¶
const SAFE_ENV_VARS = new Set([
'PATH', 'HOME', 'USER', 'LANG', 'LC_ALL', 'TMPDIR', 'XDG_RUNTIME_DIR',
'SSH_AUTH_SOCK', 'SSH_AGENT_PID', ...
])
const ANT_ONLY_SAFE_ENV_VARS = new Set([...]) // 60+ 项
环境变量白名单——这些 env vars 在 bash 命令前不需要权限检查。
两层:
- 公开白名单(SAFE_ENV_VARS)
- ANT-ONLY 扩展(ANT_ONLY_SAFE_ENV_VARS)
7. stripSafeWrappers — 95 行(行 524)¶
export function stripSafeWrappers(command: string): string {
// 移除 time, nohup, sudo -n, env -i 等安全 wrapper
}
95 行——剥离"无害 wrapper",让 time git status 变成 git status。
为什么:
- time 只是计时器
- nohup 不改变命令
- sudo -n 不需要密码
- env -i 清空 env(安全)
8. stripWrappersFromArgv — 30 行(行 678)¶
argv 版本——处理 tokenized bash。
9. BINARY_HIJACK_VARS¶
黑名单 env vars:
- LD_PRELOAD —— Linux 动态库劫持
- DYLD_INSERT_LIBRARIES —— macOS 劫持
- PATH —— 命令劫持
stripAllLeadingEnvVars 拒绝这些。
10. bashToolCheckPermission — 130 行(行 1050)¶
export const bashToolCheckPermission = (...): { decision, reason, ... } => {
// 1. 解析 bash (bashParser)
// 2. 检查 subcommand 数
// 3. 对每个 subcommand:
// - 剥 wrapper
// - 匹配 exact rule
// - 匹配 wildcard
// - 匹配 prefix rule
// 4. 返回 decision
}
130 行——单一命令的权限检查。
11. bashToolCheckExactMatchPermission — 60 行(行 991)¶
export const bashToolCheckExactMatchPermission = (...): ... => {
// 1. 解析
// 2. 对每个 subcommand:
// - exact match 检查
// 3. 返回 decision
}
精确匹配——比 wildcard 严格。
12. checkCommandAndSuggestRules — 85 行(行 1183)¶
export async function checkCommandAndSuggestRules(...): Promise<...> {
// 1. parseForSecurity
// 2. 对每个 subcommand 生成 rule suggestion
// 3. 返回 suggestions 列表
}
生成建议——"如果你要允许此命令,应该添加什么 rule"。
UX 细节:用户 deny 时给出建议,下次点一下就 allow。
13. checkSandboxAutoAllow — 95 行(行 1270)¶
Sandbox 模式——sandbox 启用时,额外自动允许某些命令。
14. checkEarlyExitDeny + checkSemanticsDeny¶
function checkEarlyExitDeny(command): boolean { ... } // 早期拒绝(如 `rm -rf /`)
function checkSemanticsDeny(command): boolean { ... } // 语义拒绝
2 个早期拒绝——快速失败,避免 LLM classifier。
15. Speculative Classifier (8 个函数)¶
const speculativeChecks = new Map<string, Promise<ClassifierResult>>()
peekSpeculativeClassifierCheck(cmd) // peek(不消费)
startSpeculativeClassifierCheck(cmd) // 启动(fire-and-forget)
consumeSpeculativeClassifierCheck(cmd) // 消费结果
clearSpeculativeChecks() // 清空
awaitClassifierAutoApproval(cmd) // 等待并应用
executeAsyncClassifierCheck(cmd, ...) // 实际执行
buildPendingClassifierCheck(cmd) // 构造 check
8 个函数——投机性预检机制:
1. 用户提交命令
2. startSpeculative 启动 LLM classifier
3. 同时做规则匹配(fast path)
4. 规则 deny → clearSpeculative(放弃)
5. 规则 allow → 直接用
6. 规则 ask → await 投机结果
7. 投机 OK → 自动 allow
8. 投机 fail → 让用户决定
性能优化——LLM classifier 通常 ~500ms,并行启动节省时间。
16. bashToolHasPermission — 900 行核心(行 1663-2567)¶
export async function bashToolHasPermission(
command: string,
toolUseContext: ToolUseContext,
): Promise<PermissionDecision> {
// ~900 行
}
900 行——主入口。
完整流程:
1. bashToolCheckExactMatchPermission —— 精确匹配
2. bashToolCheckPermission —— 通配符匹配
3. checkSandboxAutoAllow —— sandbox 自动允许
4. checkEarlyExitDeny —— 早期拒绝
5. checkSemanticsDeny —— 语义拒绝
6. checkCommandAndSuggestRules —— 生成建议
7. 启动 speculativeClassifierCheck
8. 返回 decision: { allow / deny / ask }
17. 3 个 Normalized Check¶
isNormalizedGitCommand(cmd) // 是不是 git 命令
isNormalizedCdCommand(cmd) // 是不是 cd 命令
commandHasAnyCd(cmd) // 是否包含 cd
3 个——cd 和 git 经常被特殊处理(filter、规范化)。
18. 关键设计模式¶
18.1 6 层决策¶
6 层 —— fast path 在前,慢路径在后。
18.2 Speculative 预检¶
投机性 LLM 调用——并行启动,规则决定时消费或放弃。
18.3 Strip wrappers¶
stripSafeWrappers —— time, nohup, env -i 等无害 wrapper 不影响权限。
18.4 环境变量黑/白名单¶
BINARY_HIJACK_VARS—— 拒绝SAFE_ENV_VARS—— 允许ANT_ONLY_SAFE_ENV_VARS—— ANT 内部扩展
18.5 50 subcommands 上限¶
MAX_SUBCOMMANDS_FOR_SECURITY_CHECK —— 防止慢分析。
18.6 Rule suggestion UX¶
checkCommandAndSuggestRules —— 用户 deny 时给可一键添加的 rule。
18.7 沙箱集成¶
checkSandboxAutoAllow —— sandbox 模式下额外自动允许。
19. 复杂度分析¶
| 维度 | 数字 |
|---|---|
| 总行数 | 2621 |
| 公开函数 | 25+ |
| 决策层 | 6 |
| 投机机制 | 8 个函数 |
| bashToolHasPermission | 900 行 |
| ENV 白名单 | 130+ 项 |
20. 性能特征¶
20.1 规则匹配¶
- 精确匹配:< 1ms
- 通配符匹配:< 5ms
- Classifier(投机):~500ms(并行)
20.2 50 subcommands 上限¶
50 个 subcommand 停止分析——避免
a; b; c; ...; z攻击。
21. 与其他文件的关系¶
bashPermissions.ts
├──→ bashParser.ts
├──→ bash/ast.ts
├──→ bashSecurity.ts
├──→ Tool.js
├──→ sandbox-adapter
└──→ classifier (LLM)
bashPermissions 是"决策中心"——所有层最终都委托它。
22. 关键洞察¶
22.1 6 层决策是"漏斗"¶
精确匹配 → 通配符 → sandbox → early deny → semantic deny → LLM
越往后越慢——快速路径在前。
22.2 Speculative 预检是"性能魔法"¶
LLM 分类器跑 ~500ms —— 并行启动,让用户感觉瞬间。
22.3 50 subcommand 上限是"拒绝服务防护"¶
a; b; c; ...; z 攻击——limit subcommand 数。
22.4 Rule suggestion 是"UX"¶
用户 deny 后给一键添加的 rule——降低下次 deny 概率。
22.5 Strip wrappers 减少 false positive¶
time git status 不应该被 deny——wrapper 安全。
22.6 环境变量黑/白名单双层¶
- 拒 LD_PRELOAD / DYLD_INSERT_LIBRARIES
- 允 PATH / HOME / LANG
23. 阅读建议¶
- 看 6 层决策顺序(grep
bashToolCheck) - 看 speculativeChecks Map + 8 个函数(行 1459-1663)
- 看 bashToolHasPermission 900 行(行 1663-2567)
- 看 stripSafeWrappers(行 524)—— wrapper 列表
24. 与其他深度拆解的关系¶
| 文件 | 关系 |
|---|---|
bashParser.ts |
parse |
bash/ast.ts |
AST walk |
bashSecurity.ts |
危险规则 |
BashTool.ts |
调用 bashToolHasPermission |
25. 阅读清单¶
- ✅ 看 SAFE_ENV_VARS(行 378)
- ✅ 看 stripSafeWrappers(行 524)
- ✅ 看 bashToolCheckPermission(行 1050)
- ✅ 看 speculativeChecks 8 个函数(行 1459-1663)
- ✅ 看 bashToolHasPermission(行 1663)
- 📌 对照 topics/deep-dive-bash-security.md
26. 练习任务¶
- 数决策层(grep
return.*'allow'\|'deny'\|'ask')—— 6 层 - 数白名单(grep
SAFE_ENV_VARS)—— 130+ 项 - 画 6 层决策漏斗 —— 精确 → 通配 → sandbox → deny → semantic → classifier
- 手写迷你 permission(~50 行)—— 1 个 exact + 1 个 wildcard
- 思考:speculative 预检在什么场景下会"浪费" LLM 调用?