Files

6.6 KiB
Raw Permalink Blame History

tags, create time
tags create time
tree-sitter
bash
AST
安全
权限
feature-flag
2026-06-09 22:30

TREE_SITTER_BASH — Bash AST 解析

概述

TREE_SITTER_BASH 启用一个完整的 Bash AST 解析器,用于安全验证 Bash 命令。它用完整的树遍历安全分析器取代了旧的基于正则表达式的 shell-quote 解析器。关键属性是 fail-closed:任何无法识别的内容都被归类为 too-complex 并需要用户批准。

[!info] Feature Flag: FEATURE_TREE_SITTER_BASH=1 实现状态:完整可用(纯 TypeScript 实现,~7000+ 行)

正文

关联 Feature

Feature 说明
TREE_SITTER_BASH 激活用于权限检查的 AST 解析器
TREE_SITTER_BASH_SHADOW Shadow/观测模式:运行解析器但丢弃结果,仅记录遥测

安全架构

Fail-Closed 设计

核心设计使用 allowlist 遍历模式:

  • walkArgument() 只处理已知安全的节点类型(word、number、raw_string、string、concatenation、arithmetic_expansion、simple_expansion)
  • 任何未知节点类型 -> tooComplex() -> 需要用户批准
  • 解析器加载但失败(超时/节点预算/panic)-> 返回 PARSE_ABORTED 符号(区别于"模块未加载")

解析结果

parseForSecurity(cmd) 返回:
  { kind: 'simple', commands: SimpleCommand[] }     // 可静态分析
  { kind: 'too-complex', reason, nodeType }          // 需要用户批准
  { kind: 'parse-unavailable' }                      // 解析器未加载

安全检查层次

flowchart TD
    A["parseForSecurity(cmd)"] --> B["parseCommandRaw(cmd) -> AST root node"]
    B --> C["预检查: 控制字符、Unicode 空白、反斜杠+空白、zsh 语法"]
    C --> D["walkProgram(root) -> collectCommands(root, commands, varScope)"]
    D --> E{"节点类型"}
    E -->|"command"| F["walkCommand()"]
    E -->|"pipeline/list"| G["结构性,递归子节点"]
    E -->|"for_statement"| H["跟踪循环变量为 VAR_PLACEHOLDER"]
    E -->|"if/while"| I["作用域隔离的分支"]
    E -->|"subshell"| J["作用域复制"]
    E -->|"variable_assignment"| K["walkVariableAssignment()"]
    E -->|"declaration_command"| L["验证 declare/export flags"]
    E -->|"test_command"| M["walk test expressions"]
    E -->|"其他"| N["tooComplex()"]
    D --> O["checkSemantics(commands)"]
    O --> P["EVAL_LIKE_BUILTINS eval/source/exec/trap..."]
    O --> Q["ZSH_DANGEROUS_BUILTINS zmodload/emulate..."]
    O --> R["SUBSCRIPT_EVAL_FLAGS test -v/printf -v/read -a"]
    O --> S["Shell keywords as argv0 误解析检测"]
    O --> T["/proc/*/environ 访问"]
    O --> U["jq system() 和危险 flags"]
    O --> V["包装器剥离 time/nohup/timeout/nice/env/stdbuf"]

实现架构

核心模块

模块 文件 行数 职责
门控入口 src/utils/bash/parser.ts ~110 parseCommand()、parseCommandRaw()、ensureInitialized()
Bash 解析器 src/utils/bash/bashParser.ts 4437 纯 TS 词法分析 + 递归下降解析器
安全分析器 src/utils/bash/ast.ts 2680 树遍历安全分析 + parseForSecurity()
AST 分析辅助 src/utils/bash/treeSitterAnalysis.ts 507 引号上下文、复合结构、危险模式提取
权限检查入口 src/tools/BashTool/bashPermissions.ts — 集成 AST 结果到权限决策

Bash 解析器

文件:src/utils/bash/bashParser.ts(4437 行)

  • 纯 TypeScript 实现(无原生依赖)
  • 生成与 tree-sitter-bash 兼容的 AST
  • 关键类型:TsNode(type、text、startIndex、endIndex、children)
  • 安全限制:PARSE_TIMEOUT_MS = 50、MAX_NODES = 50_000 — 防止对抗性输入导致 OOM

安全分析器

文件:src/utils/bash/ast.ts(2680 行)

核心函数:

函数 职责
parseForSecurity(cmd) 顶层入口,返回 simple/too-complex/parse-unavailable
parseForSecurityFromAst(cmd, root) 接受预解析 AST
checkSemantics(commands) 后解析语义检查
walkCommand() 提取 argv、envVars、redirects
walkArgument() Allowlist 参数遍历
collectCommands() 递归收集所有命令

AST 分析辅助

文件:src/utils/bash/treeSitterAnalysis.ts(507 行)

函数 职责
extractQuoteContext() 识别单引号、双引号、ANSI-C 字符串、heredoc
extractCompoundStructure() 检测管道、子 shell、命令组
hasActualOperatorNodes() 区分真实 ;/&&/`
extractDangerousPatterns() 检测命令替换、参数展开、heredocs
analyzeCommand() 单次遍历提取

Shadow 模式

TREE_SITTER_BASH_SHADOW 运行解析器但从不影响权限决策:

// Shadow 模式:记录遥测,然后强制使用旧版路径
astResult = { kind: 'parse-unavailable' }
astRoot = null
// 记录: available, astTooComplex, astSemanticFail, subsDiffer, ...

记录 tengu_tree_sitter_shadow 事件,包含与旧版 splitCommand() 的对比数据。用于在不影响行为的情况下收集遥测。

关键设计决策

  1. Allowlist 遍历:只处理已知安全的节点类型,未知类型直接 tooComplex()
  2. PARSE_ABORTED 符号:区分"解析器未加载"和"解析器加载但失败"。后者阻止回退旧版(旧版缺少 EVAL_LIKE_BUILTINS 检查)
  3. 变量作用域跟踪:VAR=value && cmd $VAR 模式。静态值解析为真实字符串,$() 输出使用 VAR_PLACEHOLDER
  4. PS4/IFS Allowlist:PS4 赋值使用严格字符白名单 [A-Za-z0-9 _+:.\/=\[\]-],只允许 ${VAR} 引用
  5. 包装器剥离:从 argv 前面剥离 time/nohup/timeout/nice/env/stdbuf,未知标志 -> fail-closed
  6. Shadow 安全性:Shadow 模式总是强制 astResult = { kind: 'parse-unavailable' },绝不影响权限

使用方式

# 激活 AST 解析用于权限检查
FEATURE_TREE_SITTER_BASH=1 bun run dev

# Shadow 模式(仅遥测,不影响行为)
FEATURE_TREE_SITTER_BASH_SHADOW=1 bun run dev

文件索引

文件 行数 职责
src/utils/bash/parser.ts ~110 门控入口点
src/utils/bash/bashParser.ts 4437 纯 TS bash 解析器
src/utils/bash/ast.ts 2680 安全分析器(核心)
src/utils/bash/treeSitterAnalysis.ts 507 AST 分析辅助
packages/builtin-tools/src/tools/BashTool/bashPermissions.ts ~140 权限集成 + Shadow 遥测

关联笔记