跳转至

Deep Dive | src/tools/BashTool/bashPermissions.ts 2621 行 — Bash 权限规则引擎

重要性:⭐⭐⭐(Bash 工具权限核心——规则匹配、classifier 集成、speculative 预检) 真实位置src/tools/BashTool/bashPermissions.ts2621 行角色:决定 Bash(...) 工具调用是 allow / deny / ask —— 规则匹配 + sandbox 检查 + LLM classifier 关联topics/deep-dive-bash-parser.mdtopics/deep-dive-bash-ast.mdtopics/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 常量

const MAX_SUBCOMMANDS_FOR_SECURITY_CHECK = 50
const MAX_SUGGESTED_RULES_FOR_COMPOUND = 5

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 — 规则定义

export const bashPermissionRule: (input, ...) => ... = ...

单一规则结构——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)

export function stripWrappersFromArgv(argv: string[]): string[] {
  // 从 argv 数组中移除 wrapper
}

argv 版本——处理 tokenized bash。


9. BINARY_HIJACK_VARS

export const BINARY_HIJACK_VARS = /^(LD_|DYLD_|PATH$)/

黑名单 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)

function checkSandboxAutoAllow(command): boolean {
  // sandbox 模式下自动允许某些命令
}

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 个——cdgit 经常被特殊处理(filter、规范化)。


18. 关键设计模式

18.1 6 层决策

exact match → wildcard → sandbox → early deny → semantic deny → classifier

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. 阅读建议

  1. 看 6 层决策顺序(grep bashToolCheck
  2. 看 speculativeChecks Map + 8 个函数(行 1459-1663)
  3. 看 bashToolHasPermission 900 行(行 1663-2567)
  4. 看 stripSafeWrappers(行 524)—— wrapper 列表

24. 与其他深度拆解的关系

文件 关系
bashParser.ts parse
bash/ast.ts AST walk
bashSecurity.ts 危险规则
BashTool.ts 调用 bashToolHasPermission

25. 阅读清单

  1. ✅ 看 SAFE_ENV_VARS(行 378)
  2. ✅ 看 stripSafeWrappers(行 524)
  3. ✅ 看 bashToolCheckPermission(行 1050)
  4. ✅ 看 speculativeChecks 8 个函数(行 1459-1663)
  5. ✅ 看 bashToolHasPermission(行 1663)
  6. 📌 对照 topics/deep-dive-bash-security.md

26. 练习任务

  1. 数决策层(grep return.*'allow'\|'deny'\|'ask')—— 6 层
  2. 数白名单(grep SAFE_ENV_VARS)—— 130+ 项
  3. 画 6 层决策漏斗 —— 精确 → 通配 → sandbox → deny → semantic → classifier
  4. 手写迷你 permission(~50 行)—— 1 个 exact + 1 个 wildcard
  5. 思考:speculative 预检在什么场景下会"浪费" LLM 调用?