v1.6.0 —— 权限管理
springai-agentdemo v1.6.0
在 v1.5.0 基础上的功能版(minor)。核心交付物仍是终端编码智能体 springai-code-tui。
本版只做一件事,但做得很深:权限管理。此前 code-tui 对模型开放文件系统与 shell 且零拦截——模型说改就改、说跑就跑。本版加入一层「执行前确认」:有副作用的工具调用在真正执行之前被拦下交给你拍板,并可用规则一次性放行常用动作。另加计划模式:模型只能读和查,产出计划经你批准后才动手。
⚠️ 这是本项目行为变化最大的一版。 升级后默认会弹审批面板——习惯「说一句就自动干完」的用户会明显感到多出确认步骤。若要回到旧行为,Shift+Tab切到「自动接受编辑」,或用--dangerously-skip-permissions启动(但 deny 规则与内置底线在该模式下仍然生效,这是刻意的)。
下载物仍是两个自包含运行包(解压即用,无需构建):
springai-code-tui-1.6.0-dist.tar.gz(macOS / Linux 首选)springai-code-tui-1.6.0-dist.zip(Windows 首选)
两者内容一致:启动脚本(bin/)+ 主 jar + 全部运行期依赖(lib/)+ LICENSE/NOTICE/README。运行时界面版本标识为 v1.6.0。
完整功能全景与
⚠️ 安全声明见 v1.3.0 发布说明 与 v1.0.0 发布说明;本文只列出相对 v1.5.0 的变化。
✨ 新功能:权限管理
审批面板
有副作用的调用在执行之前被拦下(拦截点在工具装饰链最外层,所以被拒的调用根本没开始跑,界面上也不会先冒出一行「工具运行中」再变失败):
⚠ 需要授权:Bash
git push origin main
↑ 命令的第 1 段 `git push origin main` 不在自动放行范围内
↳ 允许后将记下规则:Bash(git push origin main)
❯ 1. 允许一次
2. 允许,本会话不再问
3. 允许,永久
4. 拒绝,让模型换个做法
5. 拒绝并中断本回合
- 「拒绝」与「中断」是两件事:选 4 只把一条拒绝结果喂回模型、回合继续,模型据此换做法;选 5(或 Esc)才结束整个回合。
- 建议规则刻意取最窄形态:路径 → 该文件本身;命令 → 首词安全时给前缀(
Bash(mvn test:*)),首词能跑任意代码时(git/bash/python/rm…)只给整串字面量;网络 → 域名前缀。 - 命中内置底线时只有 3 项(去掉「本会话/永久」),并说明为什么——那两项在此处是谎言,任何 allow 规则都消不掉内置底线的询问。
计划模式(Shift+Tab 第三档)
Shift+Tab 在「默认 / 自动接受编辑 / 计划模式」间循环,当前档位常驻状态栏行首(默认档不占位)。
计划模式下只放行只读调查,写与命令一律拒绝(不是询问——能当场批准就等于没有计划模式)。模型改调 ExitPlanMode 交一份 markdown 计划,正文渲染进对话区,面板只放三个选项:批准并自动接受编辑 / 批准并逐个确认 / 打回继续完善(可附一句意见)。
也可用 --permission-mode plan|default|acceptEdits 启动。该参数不接受 bypass——全放行只能由 --dangerously-skip-permissions 进,否则那道显眼的开关就有了一个不显眼的同义词。
规则文件 permissions.json
两层取并集:~/.codetui/permissions.json(用户)+ <项目根>/.codetui/permissions.json(项目)。
{
"defaultMode": "default",
"allow": ["Bash(mvn test:*)", "WebFetch(https://docs.spring.io/:*)"],
"ask": ["Write(pom.xml)"],
"deny": ["Read(**/.env)", "Write(/etc/**)"]
}项目层只能收紧,不能放宽——~/.codetui/ 是你自己的配置,<项目根>/.codetui/ 是仓库带来的配置,clone 一个仓库不得让 agent 变得更宽松。据此关掉三条路径:defaultMode 两层都不接受 BYPASS(这文件 agent 自己写得到);项目层的 allow 不得是通配放行;项目层的 defaultMode 只能比用户层严。
/permissions 打开规则面板:↑↓ 选择、d 删除(先确认,删 deny 时提示明说「这会放宽权限」)、Esc 关闭。新增仍走审批面板的「允许,永久」。
内置底线(任何 allow 规则与 BYPASS 都盖不住)
排在 allow 规则之前,命中即强制询问:写 .ssh/.aws/.kube/.gnupg/.git/.codetui 配置、写 shell 启动文件与自动执行位置(LaunchAgents、.vscode/tasks.json、git hooks)、读私钥与凭据、rm -rf / 或 ~ 或变量目标(rm -rf $DIR 展开成什么无从得知)。检查穿透 sudo/env/xargs/bash -c 一类包装,也覆盖 cp/mv/curl -o/tar 等写目的地。
计划模式下这些操作直接拒绝而非询问——否则会出现「普通写操作被拒、而最危险的那批反倒是唯一能当场批准的」这种倒置。
同一个文件的多种写法
deny/ask 规则与内置底线会折叠大小写、并解析符号链接(含目标尚不存在的悬空链接),故 deny Write(/etc/**) 拦得住 /ETC/passwd(macOS APFS 上那是同一个文件),经链接指向 .ssh/ 的写入也认得出。
allow规则只认原写法,这是设计不是疏漏:deny 误拦你看得见、能调整;allow 误放行不可逆。所以放宽匹配只在「问一下无害」的方向上做。
子 agent 与 MCP
子 agent(Task/ParallelTasks)与 MCP 工具共用同一个权限引擎,因装饰链共用而自动纳管。并发触发时审批面板逐个弹。MCP 工具默认询问(未登记工具一律保守 ASK)。
计划模式下子 agent 会收到一段专属提示(说明自己处于只读调查阶段、把发现报告回主 agent 就是交付)——刻意不与主 agent 版统一,因为主 agent 版指向 ExitPlanMode,而子 agent 没有那个工具,照抄等于指一条走不通的路。
🔧 其它变化
- 输入框的
Shift+Tab与裸Tab现在都能到达应用:TamboUI 的焦点导航此前会吞掉它们,导致斜杠菜单的 Tab 补全与/mcp面板的 Tab 展开一直是死代码(无人发现,因为单测走的是绕过路由器的入口)。已解绑焦点导航。 - 「允许,永久」的确认行现在打出规则文件的绝对路径,且由真正写盘的那一侧在写完之后回报——此前是在写盘发生前就用完成时描述它,且写失败也不会更正。
⚠️ 权限层不是沙箱
必须分清它是什么、不是什么:
权限层管的是「要不要做这一步」,不是「能做到多远」。 一旦你按下允许,那次调用照样以你的用户权限执行、不受任何目录边界约束。
它降低的是「模型自作主张、或被提示注入后无声搞破坏」的风险;它不降低「你自己按了允许」之后的风险,也不是隔离容器。已知弱点(诚实列出,别高估它):
- 审批疲劳是最现实的风险——弹得多就容易一路按「允许」,那与没有权限层无异。
- 内置底线是黑名单不是白名单:没枚举到的自然漏过。
- 硬链接认不出:
ln ~/.ssh/id_rsa /tmp/x之后/tmp/x路径上没有任何可疑之处,文件系统也不提供同 inode 反查。 - 在
$HOME下直接运行时,「系统位置」检查对整个家目录失效(家目录整体豁免是设计如此)。 - 只读操作不询问(
Read/Grep/Glob),读私钥/凭据仍被内置底线拦下,但「读了什么」整体不在审批范围内。
详见 code-tui README 的安全声明 与 SECURITY.md。
⬆️ 升级须知
- 无破坏性变更:旧会话、旧
mcp.json、旧技能目录照常可用;不配任何permissions.json也能跑(那时一切按模式默认判定)。 - 但默认行为变了:升级后会开始弹审批。要回到接近旧行为,
Shift+Tab切到「自动接受编辑」(工作区内的改动自动放行),或--dangerously-skip-permissions(deny 规则与内置底线仍生效)。 - 建议:先在一个可随意丢弃的项目里跑几轮,把高频动作用「允许,永久」记进
permissions.json,之后就不会再被打扰。
🔐 校验(SHA-256)
4564837e8c5f8e82ed30deefb3541db80efc166e4edbb810cf600d6e4614699c springai-code-tui-1.6.0-dist.tar.gz
baa8a34e794253af127e90c28e3e62940784bd7a8e0fe57e6f19b3fdc3829607 springai-code-tui-1.6.0-dist.zip
shasum -a 256 -c <<'EOF'
4564837e8c5f8e82ed30deefb3541db80efc166e4edbb810cf600d6e4614699c springai-code-tui-1.6.0-dist.tar.gz
baa8a34e794253af127e90c28e3e62940784bd7a8e0fe57e6f19b3fdc3829607 springai-code-tui-1.6.0-dist.zip
EOF📄 许可
Apache License 2.0。发布包内随附 LICENSE 与 NOTICE(含所分发第三方库:Spring AI / Spring Boot / spring-ai-community 为 Apache 2.0,TamboUI 为 MIT)。本版未引入任何新的第三方依赖——权限层全部是本模块自写代码。
环境:JDK 17+,macOS / Linux / Windows。