凿子
 
🪛 Rust为代理提供精确文件操作。Unix原生工具,最小的上下文占用,严格的路径限制:直接与Chisel MCP一起使用或自带MCP,可嵌入Rust、Python、Nodejs中的任何MCP服务器。
https://github.com/user-attachments/assets/af84f1af-db47-4e42-808b-00861504cd34
______________________________________________________________________
包括代理技能 —skills/chisel/SKILL.md教导代理人如何以最高效率使用凿子。安装方式:npx skills add ckanthony/Chisel
加强安保 --跨两层验证属性:MCP服务器(chisel)以及便携式核心库(chisel-core).请参阅 安全模型 完整的细分部分。
______________________________________________________________________
目录
- 二进制 - 码头工人 - 配置您的MCP客户端
______________________________________________________________________
动机
大多数MCP文件工具给LLM一张空白画布:读任何东西,写任何东西,犯任何错误。Chisel采取了相反的方法:
- 减少上下文开销 --每个工具调用都很紧凑。文件编辑完成
patch_apply:该模型只发送一个统一的diff,而不是重写整个文件,因此大文件编辑的成本只是令牌的一小部分 - 熟悉的命令模式 —
shell_exec公开相同的Unix工具(grep,sed,awk,find,cat,…)LLM已经从训练数据中了解得很好,因此提示保持简短,输出是可预测的 - 精度高于灵活性 --固定的白名单和严格的路径限制意味着模型不能意外地逃脱作用域或运行任意命令
- 安全第一 --承载令牌认证,
127.0.0.1-默认情况下,只有绑定、符号链接感知的根限制、原子写入和只读模式都处于启用状态 - 可重复使用的核心 —
chisel-core是一个普通的同步Rust库;任何MCP服务器(Rust、Node.js通过WASM、Python通过WASM)都可以嵌入它,而无需运行第二个进程
真实世界演示
同一markdown文件上的六个任务。左:典型的MCP文件服务器。右:凿子。
文件: docs/api.md --300条线,6个集管,一段约20条线。
______________________________________________________________________
任务1——查找所有标题
# Typical # Chisel
tool: read_file tool: shell_exec
path: /data/docs/api.md command: grep
args: ["-n", "^#", "/data/docs/api.md"]
← 300 lines returned (~3 000 tokens) ← 6 lines returned (~30 tokens)
model must scan the whole file 1:# API Reference
45:## Authentication
89:## Endpoints
134:## Request Format
178:## Response Format
234:## Errors任务2——阅读以下内容 ## Endpoints
# Typical # Chisel
tool: read_file (again, or re-use above) tool: shell_exec
path: /data/docs/api.md command: sed
args: ["-n", "/^## Endpoints/,/^## /p",
← 300 lines returned again (~3 000 tokens) "/data/docs/api.md"]
model must locate the section in context
← 44 lines returned (~440 tokens)
only the Endpoints section任务3——编辑该部分中的一行
# Typical # Chisel
tool: write_file tool: patch_apply
path: /data/docs/api.md path: /data/docs/api.md
content: --- a/docs/api.md
+++ b/docs/api.md
← 300 lines uploaded (~3 000 tokens) @@ -91,1 +91,1 @@
any hallucination corrupts the file -GET /v1/items
+GET /v2/items
← 7 lines uploaded (~50 tokens)
hunk mismatch → PatchFailed, file untouched任务4——全部替换 - 随着 : 在该章节中
# Typical # Chisel
tool: read_file tool: shell_exec
path: /data/docs/api.md command: sed
args: ["-i", "s/-/:/g",
← 300 lines returned (~3 000 tokens) "/data/docs/api.md"]
tool: write_file
content: ← 1 line call, 0 file content transmitted
← 300 lines uploaded (~3 000 tokens) sed runs the replacement in-place
Total: ~12 000 tokens Total: ~520 tokens (23× less)任务5——模型尝试运行 rm -rf ~
# Typical # Chisel
(no shell tool exposed) tool: shell_exec
command: rm
args: ["-rf", "~"]
not applicable — typical MCP file
servers have no shell tool, so the ← CommandNotAllowed
model would need a separate shell "rm" is not in the whitelist.
MCP or use write_file to script it Permitted: grep sed awk find cat
head tail wc sort uniq cut tr
diff file stat ls du rg
process is never spawnedrm,bash,sh,curl,chmod,sudo--这些都不在白名单上。 该列表在编译时是固定的;模型在运行时无法对其进行扩展。
任务6——模型尝试编辑 /Users/home/.ssh/config 直接
# Typical # Chisel
tool: write_file tool: patch_apply
path: /Users/home/jor/.ssh/config path: /Users/home/jor/.ssh/config
content: patch:
← succeeds if the server process ← OutsideRoot
has filesystem access — no path resolved path /Users/home/.ssh/config
confinement in a naive file server does not start with root /data
I/O is never performed每一条路,包括那些经过的路 shell_exec --根据 在任何I/O或进程生成之前配置根。根之外的绝对路径 无论调用哪个工具,总是被拒绝。______________________________________________________________________
上下文成本比较
估算使用 克劳德·十四行诗4.6 标记化:典型的源代码平均值 约10个代币/行 (标识符、标点符号和空格在BPE下都算作标记)。
单次编辑——500行文件,更改5行:
天真(read_file → write_file) | 凿子(patch_apply) | 减少 | |
|---|---|---|---|
| 令牌在(上传) | ~5000(完整文件) | ~120(11个差异行+标头) | 42× |
| 令牌输出(模型输出) | ~5000(完整文件重写) | ~15(成功确认) | 333× |
| 往返总计 | ~10 000 | ~135 | ~74× |
| 故障模式 | 无声幻觉会损坏整个文件 | PatchFailed --原封不动 | -- |
读取/搜索——2000行文件:
| 任务 | 天真(read_file 满) | 凿子(shell_exec) | 减少 |
|---|---|---|---|
| 查找一个符号 | ~20 000个标记(完全读取) | ~40个标记(grep 匹配的线条) | 500× |
| 计数出现次数 | ~20 000个令牌 | ~5个令牌(grep -c 整数) | 4 000× |
| 提取第40-60行 | 约20000个代币 | 约210个代币(sed -n '40,60p') | 95× |
| 目录树 | ~2000个令牌 | ~300个令牌(find / ls -R) | 67× |
节省与文件大小呈线性关系。一个2000行的文件的成本是上述500行基线的4倍。
______________________________________________________________________
工具
在任何I/O之前,每个路径参数都被规范化并限制在配置的根目录中-- .. 遍历和符号链接转义被拒绝。这种限制是在里面执行的 chisel-core 并且当库直接嵌入时同样适用。
使用MCP服务器时(chisel),所有工具还需要 Authorization: Bearer .
| 工具 | 说明 | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
patch_apply | 原子地应用统一的diff;接受原始或“diff”`fenced patches — primary edit tool; sends only changed lines, not the full file | 附加 | Append content to an existing file | write_file | Write (create or overwrite) a file; creates parent dirs automatically | create_directory | Create a directory tree (mkdir-psemantics) | move_file | Move or rename a file within root | shell-exec | Run a whitelisted command —grep sed awk查找猫头尾wc排序uniq切割tr diff文件统计ls du rg\ |
完整参考: docs/tools.md
______________________________________________________________________
带上自己的MCP
Chisel在独立服务器旁边附带了两个可嵌入的库。两者都不包含任何HTTP、MCP协议或异步运行时依赖关系——将它们放入您自己的服务器并完全拥有传输。
| 包装 | 它是什么 | 使用它时 |
|---|---|---|
chisel-core | 纯Rust同步库——路径限制、所有文件操作、shell exec | 编写Rust MCP服务器 |
chisel-wasm | chisel-core 编译为 wasm32-wasip1 | 在Node.js、Python、Deno或任何WASI运行时编写MCP服务器 |
完整集成指南→ 凿芯/README.md
______________________________________________________________________
独立使用
二进制
选项A——下载预构建的二进制文件(推荐)
去 最新版本 并下载适用于您平台的二进制文件:
| 平台 | 文件 |
|---|---|
| macOS苹果硅 | chisel-macos-arm64 |
| macOS英特尔 | chisel-macos-x86_64 |
| Linux x86-64 | chisel-linux-x86_64 |
| Linux ARM64 | chisel-linux-arm64 |
# Make executable and run
chmod +x chisel-macos-arm64 # adjust filename for your platform
MCP_APP_SECRET=mysecret ./chisel-macos-arm64 --root /path/to/data选项B——从源代码构建
cargo build --release -p chisel跑步
# Secret via env var (preferred)
MCP_APP_SECRET=mysecret ./chisel --root /path/to/data
# Or via --secret flag (env var takes precedence if both set)
./chisel --root /path/to/data --secret mysecret
# Read-only mode (shell_exec still works; writes are blocked)
MCP_APP_SECRET=mysecret ./chisel --root /path/to/data --read-only服务器绑定到 127.0.0.1:3000 默认情况下。使用 --port 更改端口。
码头工人
在Docker中运行Chisel的三种方法——选择一种适合你工作流程的方法。
选项1-Docker Compose(推荐)
# 1. Create your .env
echo "MCP_APP_SECRET=changeme" > .env
# 2. Create the data directory that will be exposed to the LLM
mkdir -p data
# 3. Start (builds the image on first run, then stays running)
docker compose up -d
# Tail logs
docker compose logs -f
# Stop
docker compose downdocker-compose.yml 山丘 ./data → /data 在容器内并捆绑 127.0.0.1:3000:3000 --端口永远不会暴露在localhost之外。
选项2-- docker run
# Build
docker build -t chisel:latest .
# Run (replace /absolute/path/to/data with your actual data directory)
docker run -d \
--name chisel \
-e MCP_APP_SECRET=changeme \
-v /absolute/path/to/data:/data \
-p 127.0.0.1:3000:3000 \
--restart unless-stopped \
chisel:latest
# Read-only mode (writes blocked, shell_exec still works)
docker run -d \
--name chisel \
-e MCP_APP_SECRET=changeme \
-v /absolute/path/to/data:/data:ro \
-p 127.0.0.1:3000:3000 \
chisel:latest chisel --root /data --read-only选项3--自定义端口
docker run -d \
--name chisel \
-e MCP_APP_SECRET=changeme \
-v /absolute/path/to/data:/data \
-p 127.0.0.1:8080:3000 \
chisel:latest主机端口 8080 集装箱港口地图 3000。将您的MCP客户端URL更新为 http://127.0.0.1:8080/mcp 因此。
容器以非root用户身份运行(chisel)永不束缚0.0.0.0。要进行远程访问,请将Caddy或nginx放在前面——请参阅 反向代理的背后.
配置您的MCP客户端
{
"mcpServers": {
"chisel": {
"url": "http://127.0.0.1:3000/mcp",
"headers": {
"Authorization": "Bearer "
}
}
}
}______________________________________________________________________
反向代理(Caddy)背后
奇塞尔故意拒绝捆绑 0.0.0.0远程或多客户端访问通过处理TLS的反向代理。
Caddy--自动HTTPS
mcp.yourdomain.com {
reverse_proxy 127.0.0.1:3000
}Caddy自动提供Let's Encrypt证书。承载令牌仍然对每个请求进行端到端的身份验证。
# Install Caddy (macOS)
brew install caddy
# Run
caddy run --config Caddyfile您的MCP客户端URL变为 https://mcp.yourdomain.com/mcp.
引擎X
server {
listen 443 ssl;
server_name mcp.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/mcp.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mcp.yourdomain.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
}
}______________________________________________________________________
加长凿子
看 凿芯/README.md 完整的集成指南包括:
- 带代码示例的Rust API参考
spawn_blocking异步处理程序模式- Node.js(≥22)WASM/WASI集成
- python
wasmtime-py)WASM集成 - 错误类型和安全属性
______________________________________________________________________
工作区布局
chisel/
├── chisel/ # HTTP server binary (MCP Streamable HTTP transport)
├── chisel-core/ # Portable sync library — no HTTP, no async, no MCP protocol
└── chisel-wasm/ # wasm32-wasip1 build of chisel-core for Node.js / Python / Denograph TD
A[LLM / MCP client] -->|HTTP + Bearer| B[chisel binary]
B --> C[chisel-core]
D[Your Rust MCP server] --> C
E[Node.js MCP server] -->|WASI| F[chisel-wasm .wasm]
G[Python MCP server] -->|WASI| F
F --> C______________________________________________________________________
安全模型
安全属性分为两层。每一行都由本节底部引用的测试套件进行验证。
chisel --MCP服务器/HTTP层
| # | 属性 | 机制 | 默认值 |
|---|---|---|---|
| 1 | 承载令牌身份验证 --每个请求都经过身份验证 | subtle::ConstantTimeEq定时安全比较;缺失或空洞的秘密→ 进程在启动时退出 | 必需 |
| 2 | 速率限制 --暴力和失控代理保护 | governor 代币桶;超额请求→ HTTP 429 在检查身份验证之前 | 100请求/秒 |
| 3 | 请求车身盖 --防止记忆耗尽 | axum::DefaultBodyLimit;超大的身体→ HTTP 413 在任何解析之前 | 4 MiB |
| 4 | 审计日志 --每个工具操作均可追溯 | tracing::info 关于成功, tracing::warn 关于失败;记录操作名称、路径、错误 | info |
| 5 | 仅环回绑定 --无意外公众曝光 | `TcpListener::bind("127.0.0.1: | |
"); 0.0.0.0` 从未使用过 | -- |
chisel-core --可移植库(在每次操作中强制执行,包括嵌入式使用)
| # | 属性 | 机制 |
|---|---|---|
| 6 | 内核强制根限制 --目录遍历、符号链接转义、TOCTU全部被阻止 | cap_std::fs::Dir;通过的每个路径组件 openat(fd, component, O_NOFOLLOW);限制是在I/O期间在内核级别强制执行的,而不是在I/O之前在用户空间强制执行的 |
| 7 | 原子写入 --失败的补丁永远不会损坏目标文件 | Dir::create(".name.PID.tmp") + Dir::rename(tmp → target)两个操作都被限制在同一个根fd内;如果发生任何故障,tmp文件将被丢弃,原始文件将保持不变 |
| 8 | 只读模式 --毯式写保护 | check_writable(read_only) 在每个写操作中的任何I/O之前运行;没有代码路径绕过它 |
| 9 | 壳牌白名单+直接 execve --无注入,无任意命令 | 修复编译时白名单; std::process::Command 直接产卵(否 sh -c);通过验证路径式参数 validate_path 产卵前 |
graph LR
req[Incoming request] --> body{Body ≤ limit?\nDefaultBodyLimit}
body -- too large --> 413[HTTP 413]
body -- ok --> rate{Rate limit\ntoken-bucket}
rate -- exceeded --> 429[HTTP 429]
rate -- ok --> auth{Bearer token\nconstant-time compare}
auth -- reject --> 401[HTTP 401]
auth -- pass --> path{Path confinement\ncap-std openat + O_NOFOLLOW}
path -- outside root --> err[OutsideRoot error]
path -- inside root --> ro{Read-only mode?}
ro -- write op --> readonly[ReadOnly error]
ro -- read / shell --> exec[Execute tool]
exec --> audit[Audit log\ntracing::info/warn]
exec --> atomic[Atomic write\nDir::create + Dir::rename]防止攻击和误用
每一层都针对一类特定的故障——意外的或故意的。
1.身份验证--未经授权的访问
每个HTTP请求都必须携带 Authorization: Bearer .比较使用 subtle::ConstantTimeEq,无论匹配多少字符,都需要相同数量的CPU周期。基于时间的暴力攻击无法成功,因为没有时间信号泄漏。
如果密钥为空或不存在,服务器将拒绝启动——配置错误是一个严重错误,而不是无声地回退到无身份验证。
2.路径限制——从根目录转义
这是核心保证。所有文件系统工具(patch_apply, append, write_file, create_directory, move_file)仅通过a运营 cap_std::fs::Dir 句柄位于配置的根目录。
input string
→ strip root prefix → relative path
→ cap_std::fs::Dir::open / write / rename …
└─ kernel: openat(root_fd, "sub/file", O_NOFOLLOW)
openat(sub_fd, "file", O_NOFOLLOW)路径的每个组成部分都经过 openat 随着 O_NOFOLLOW内核强制限制——不能绕过用户空间前缀检查:
| 攻击 | 示例输入 | 发生了什么 |
|---|---|---|
| 目录遍历 | /data/sub/../../etc/passwd | .. 按fd跟踪的组件;root以上的escape被内核阻塞→ 错误 |
| 绝对路径旁路 | /etc/hosts | 删除根前缀;剩余路径仅限于根fd→ OutsideRoot |
| 组件中的Symlink | /data/link/file 哪里 link → /etc | O_NOFOLLOW 上 link open → 内核拒绝→ 错误 |
| TOCTU swap | 检查时的有效路径,在I/O之前交换为符号链接 | 没有单独的检查/使用窗口——在I/O本身期间强制执行限制 |
validate_path (早期版本的用户空间规范化+前缀检查)仍然专门用于 shell_exec 路径参数,我们将字符串传递给生成的进程 cap-std 不能限制。
3.Shell注入——任意命令执行
shell_exec 做 不 调用shell解释器。它召唤 std::process::Command 直接将命令和参数作为单独的操作系统级字符串:
shell_exec("grep", ["-r", "foo", "/data"])
→ execve("/usr/bin/grep", ["-r", "foo", "/data"]) ← no sh -c wrapper外壳元字符(;, &&, |, $()、回溯等)作为文本字节传递给目标进程。没有外壳来解释它们。
固定编译时白名单(grep sed awk find cat head tail wc sort uniq cut tr diff file stat ls du rg)在生成进程之前进行检查。任何不在列表中的命令都会返回 CommandNotAllowed 立即——该过程从未开始。
路径式参数(以开头 / 或含有 ..)通过根进行验证 validate_path 在过程开始之前。
4.部分写入——补丁失败导致文件损坏
patch_apply 从不直接写入目标文件。水流完全被限制在 cap-std 导演:
1. Parse and validate the diff
2. Dir::create(".filename.PID.tmp") ← confined temp file, same directory
3. On success → Dir::rename(tmp, target) ← single syscall, cannot be interrupted mid-write
4. On failure → return PatchFailed, tmp is dropped and cleaned up如果大块上下文与当前文件不匹配(自diff生成以来文件已经漂移),则操作在步骤1中止,原始文件永远不会被触及。步骤2和3之间的进程崩溃会导致 .tmp 文件——原件仍然完好无损。
5.只读模式——毯式写保护
从...开始 --read-only 导致所有五个写入工具(patch_apply, append, write_file, create_directory, move_file)返回 ReadOnly 立即执行任何I/O操作。检查在内部进行 chisel-core 在任何磁盘访问之前,都没有绕过它的代码路径。
shell_exec 在只读模式下保持可用,因为它只读取(白名单中的命令都是检查工具; mkdir 和 mv 被明确排除在白名单之外)。
6.速率限制——暴力破解和失控代理保护
每个请求都通过一个令牌桶速率限制器(governor)在认证之前。当配置的速率(默认值: 100个请求/秒)超过,服务器立即返回 HTTP 429 Too Many Requests 不做任何工作。
这可以防止两类威胁:
- 令牌暴力:即使存在部分形式的泄露秘密,攻击者也无法以超过配置速率的速度枚举令牌。
- 失控代理循环:发生故障的LLM客户端淹没服务器,在导致资源耗尽之前会被限制。
配置为 --rate-limit (或设置为 0 禁用)。限制器是最外层——超过速率的请求永远不会到达身份验证检查。
7.请求身体帽——防止内存耗尽
所有传入请求主体的上限为 4 MiB 默认情况下(DefaultBodyLimit).在进行任何解析、身份验证或工具分派之前,会拒绝过大的主体。
配置为 --body-limit 。对于典型的LLM使用(统一差异和文件内容),4 MiB是慷慨的——只有在您有意发送大文件写入时才增加。
8.审计日志——操作可追溯性
每次工具调用都会发出一个结构化的 tracing 记录操作名称、目标路径(或命令)以及成功或失败的日志行:
INFO chisel::tools::filesystem op=patch_apply path=/data/foo.txt
WARN chisel::tools::filesystem op=write_file path=/etc/passwd error=OutsideRoot { ... }
INFO chisel::tools::shell op=shell_exec cmd=grep exit_code=0日志详细程度通过以下方式控制 RUST_LOG 环境变量(例如。 RUST_LOG=chisel=debug).默认级别为 info,它捕获每个工具调用结果,而不会用框架内部淹没输出。
9.网络曝光——无意外公开绑定
服务器调用 TcpListener::bind("127.0.0.1: ") --不是 0.0.0.0进程本身不可能接受来自机器外部的连接。远程访问必须通过反向代理(Caddy、nginx)进行路由,这是TLS终止和任何其他访问控制的地方。
Docker镜像以非root用户身份运行(mcp)以及 docker-compose.yml 将港口映射为 127.0.0.1:3000:3000,即使在容器内也能保持环回限制。
安全测试覆盖率
上述每个属性都经过专门的测试套件验证,测试套件位于 [chisel/tests/security.rs](chisel/tests/security.rs). 奔跑 cargo test --test security -p chisel.
| 属性 | 测试 |
|---|---|
| §1身份验证 | auth_missing_secret_is_hard_error · auth_empty_secret_is_hard_error · auth_missing_header_returns_401 · auth_wrong_token_returns_401 · auth_basic_scheme_returns_401 · auth_prefix_of_secret_returns_401 · auth_valid_token_passes |
| §2路径限制 | path_directory_traversal_is_blocked · path_absolute_outside_root_returns_outside_root_error · path_symlink_in_component_is_blocked · path_toctou_symlink_swap_is_blocked · path_deeply_nested_outside_root_is_blocked |
| §3壳体注射 | shell_dangerous_commands_blocked_before_spawn · shell_metacharacters_are_literal · shell_path_arg_outside_root_blocked_before_spawn · shell_traversal_in_arg_blocked_before_spawn |
| §4部分书写 | partial_write_failed_patch_leaves_file_intact · partial_write_no_tmp_artefact_on_failure |
| §5只读模式 | readonly_all_write_tools_are_blocked · readonly_shell_exec_remains_available · readonly_no_disk_mutation_occurs |
| §6网络绑定 | network_bind_address_is_loopback_only · network_sse_endpoint_returns_404 |
每次CI运行时,所有23个测试都通过。失败意味着记录在案的安全保证已经倒退。
$ cargo test --test security -p chisel
running 23 tests
test auth_empty_secret_is_hard_error ... ok
test auth_missing_secret_is_hard_error ... ok
test network_bind_address_is_loopback_only ... ok
test path_absolute_outside_root_returns_outside_root_error ... ok
test path_deeply_nested_outside_root_is_blocked ... ok
test readonly_all_write_tools_are_blocked ... ok
test readonly_no_disk_mutation_occurs ... ok
test path_directory_traversal_is_blocked ... ok
test shell_dangerous_commands_blocked_before_spawn ... ok
test shell_path_arg_outside_root_blocked_before_spawn ... ok
test path_symlink_in_component_is_blocked ... ok
test shell_traversal_in_arg_blocked_before_spawn ... ok
test partial_write_failed_patch_leaves_file_intact ... ok
test partial_write_no_tmp_artefact_on_failure ... ok
test path_toctou_symlink_swap_is_blocked ... ok
test readonly_shell_exec_remains_available ... ok
test shell_metacharacters_are_literal ... ok
test auth_missing_header_returns_401 ... ok
test auth_valid_token_passes ... ok
test auth_basic_scheme_returns_401 ... ok
test auth_prefix_of_secret_returns_401 ... ok
test auth_wrong_token_returns_401 ... ok
test network_sse_endpoint_returns_404 ... ok
test result: ok. 23 passed; 0 failed______________________________________________________________________
发展
# Run all tests
cargo test --workspace
# Run only the server tests
cargo test -p chisel
# Build the WASM target
rustup target add wasm32-wasip1
cargo build --target wasm32-wasip1 -p chisel-wasm
# Build Docker image
docker build -t chisel:dev .______________________________________________________________________
平台支持
| 平台 | 服务器二进制文件(chisel) | chisel-core (lib,无shell) | chisel-wasm |
|---|---|---|---|
| Linux(x86_64,arm64) | ✅ 全力支持 | ✅ | ✅ |
| macOS(苹果硅、英特尔) | ✅ 全力支持 | ✅ | ✅ |
| Windows | ❌ 不支持 | ⚠️ 编译,未测试 | ✅ |
Linux/macOS --主要目标。所有九个安全属性都成立。Docker镜像是基于Debian的。 shell_exec 白名单(grep, sed, awk, find, cat, ls,…)假设一个标准的Unix环境。
视窗 --服务器二进制文件不支持,原因有三:
shell_exec白名单完全是Unix工具;大多数在Windows上本机不存在cap-std内核限制使用POSIXopenat + O_NOFOLLOW语义学;Win32重分析点/连接处理不同- 创建Symlink需要提升权限(
SeCreateSymbolicLinkPrivilege)--没有管理员或开发人员模式,安全测试无法运行
**chisel-wasm\*\*--完全便携。WASM不依赖于操作系统;无论主机操作系统如何,在任何支持WASI的运行时(Node.js≥22、Deno、Wasmtime)上都能以相同的方式运行。 shell_exec 被排除在WASM构建之外。
______________________________________________________________________
贡献
欢迎捐款。一些指导方针:
- Bug修复和小改进 --直接打开PR。
- 新工具或行为改变 --在编写代码之前,先打开一个问题,就范围达成一致。
- 安全问题 --不要公开问题。提交一份私人报告,并包括复制步骤。
提交前:
cargo test --workspace # all tests must pass
cargo test --test security -p chisel # security suite must be green
cargo clippy --workspace -- -D warnings
cargo fmt --check新的安全相关代码应在中附带匹配测试 chisel/tests/security.rs 它所覆盖的攻击向量的名称。
______________________________________________________________________
今后的考虑
S3/R2对象存储后端
一个潜在的扩展是一个薄同步层,它将S3或R2对象水合到本地暂存目录中(RAM支持或 tmpfs),通过正常方式对该目录运行所有Chisel操作 chisel-core 路径,然后在完成时将更改的对象刷新回来。
代理将仅与Chisel交互——路径限制、原子修补和shell工具的行为都是相同的。S3/R2将纯粹作为持久层,对模型透明。
在此之前存在的开放性问题是可行的:对同一对象的并发写入需要乐观锁定(基于ETag的检查和刷新时的交换),以及本机 cap-std 对象存储不存在等效项,因此必须在暂存目录级别而不是存储层实施限制。核心 shell_exec 白名单还假设一个Unix文件系统,并要求在运行任何命令之前,对象在本地完全物化。
