@cyia/pi-block-find-root
v0.3.0
Published
pi 扩展:拦截 find 查询禁用路径
Maintainers
Readme
pi-block-find-root
pi 扩展:拦截 find 查询禁用路径。运行环境固定 Linux / msys2,只处理 POSIX 路径。
find(path="/etc", pattern="*")
→ 禁止使用 /etc 查询内容
bash(command="find / -name aaa") # 需 blockBash: true
→ 禁止使用 bash 调用 find 查询 /(命中:/)⚠️ 防误操作的护栏,不是安全边界。
read、grep等工具不受影响; bash 里的find会被解析拦截,但不可能覆盖所有变形(见下)。
配置
写在 pi 的 settings.json,项目覆盖全局:
| 文件 | 作用域 |
| --- | --- |
| ~/.pi/agent/settings.json | 全局 |
| .pi/settings.json | 当前项目(需项目被信任) |
{
"blockFindRoot": {
"forbiddenPaths": ["/", "/etc"],
"blockBash": true
},
"defaultTimeout": 120
}| 键 | 默认 | 作用 |
| --- | --- | --- |
| forbiddenPaths | ["/"] | 禁用路径列表 |
| blockBash | false | 是否检测 bash 命令里的 find。不写就是关 |
find 工具本身始终受管,blockBash 只管 bash 那一条。逐键回退:
项目写了哪个键就用项目的,没写的键去看全局,都没有则用默认值。
默认超时
bash 命令没写 timeout 就补上,默认 120s。配置一个数:
{ "defaultTimeout": 300 }模型自己给了 timeout 就不动它。长驻命令(dev server、watch)自己写个大的,
或者 "defaultTimeout": 2147483。实现在 src/default-timeout.ts。
命中规则
输入路径 等于 禁用路径,或 在该路径之下。
以 forbiddenPaths: ["/etc"] 为例:
| find 的 path | 结果 |
| --- | --- |
| /etc | 🚫 |
| /etc/passwd | 🚫 |
| /etcfoo | ✅ 放行(不是子路径) |
| 省略 | 按 cwd 判定 |
比较前只做轻量归一:去掉尾部通配符(/etc/* → /etc)。
不展开 ~、不解析符号链接,按 POSIX 路径原样比。
bash 里的 find(默认关,blockBash: true 才开)
解析逻辑全部在 src/bash-find-parser.ts(纯函数,不依赖 pi,可单独测):
import { extractFindPaths } from "./bash-find-parser.ts";
extractFindPaths("sudo timeout 1 find / -name aaa"); // → [["/"]]职责划分:
| 文件 | 干什么 |
| --- | --- |
| src/bash-find-parser.ts | 只解析:从 command 里抽出每次 find 的路径参数 |
| src/path-match.ts | 只比较:路径归一 + 「等于或在之下」 |
| src/block-find-root.ts | 只拦截:读配置、把上面两个接起来、返回 { block: true } |
| test/ | 三个文件各一套用例,共 170+ 条 |
解析步骤:
lexSegments— 一遍扫描同时切段 + 分词:引号外的; & | ( ) 换行是段边界, 引号里的不算;$( )与反引号(单引号外)会递归解析里面的内容;\x取字面量;findCallArgs— 跳过命令词前面的VAR=赋值、数字参数、包装器 (sudoenvtimetimeoutnohupnicexargswatchstdbufbusyboxcommand) 和选项(含sudo -u root这种带值的);- 命令词是
find(含/usr/bin/find,大小写不敏感)就收下它后面的参数;findstr、echo find /、git find之类不算;命令词是 shell 则递归解析一层; pathCandidates— 丢掉选项(-name/-path/-maxdepth等连值一起丢)、 丢掉重定向(2>/dev/null)、-exec系列直接截断(后面是子命令);find没写路径参数时由block-find-root按cwd判定。
已覆盖的变形:sudo -u root find /etc、timeout 1 find /、find "/"、fi\nd /、
find /etc\ dir(带空格的真实路径)、x=$(find /)、y=`find /etc`、
echo "a $(find /)"(双引号里会真执行 → 拦)、bash -c "find /"、a; find /etc。
已知拦不住:路径来自 stdin/变量展开后再交给别的程序、自写脚本里调 find、
docker / ssh 里跑 find、read/grep 直接读禁用路径。护栏而已,别当安全边界。
本地试
本仓库 .pi/settings.json 已配好规则,.pi/extensions/ 里有转发文件,
直接在这个目录跑 pi 即可。
开发
npm install
npm run typecheck
npm test # node --test,170+ 条测试分三层:
| 文件 | 盖住什么 |
| --- | --- |
| test/bash-find-parser.test.ts | 解析:该认的必须认,不该认的绝不认 |
| test/path-match.test.ts | 比较:等于 / 子路径 / 兄弟目录不误伤 / 通配符归一 |
| test/block-find-root.test.ts | 端到端:喂真实 tool_call 事件,临时目录写自己的 settings |
License
MIT
