关于 archive-zip-unzip-bomb-guard
archive-zip-unzip-bomb-guard 是用于创建、检查和解压 ZIP 归档的本地 MCP 服务。它会在解压前检查归档头信息,并防范路径遍历、符号链接和压缩炸弹。
主要功能
- 01按文件和 glob 模式创建 ZIP
- 02列出条目、大小并标记风险
- 03通过安全检查和试运行解压
- 04无需解压即可读取文本条目
- 05向现有归档添加文件
- 06打包一个月的发票和导出文件
适用场景
- 01打开邮件附件前检查归档
- 02解压文件时防范路径遍历和压缩炸弹
- 03无需全部解压即可读取归档中的 README
- 04为会计师打包月度发票和导出文件
MCP 相关
向 MCP 客户端提供 ZIP 创建、检查、解压及相关工具。服务在本地运行,不会发起网络请求。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
mcp-zip
在当前对话中创建 zip、查看 zip 内容并解压。使用 glob 打包一个文件夹
(**/*.csv、除 node_modules 外的所有内容)。无需解压,就能读取压缩包中的 README。
询问别人发来的 zip 里有什么,即可在打开前获知内容:绝对路径、..、符号链接、
重复文件名,以及一个在 199 KB 文件中声称大小为 200 MB 的条目。将一个月的发票、
报价单和导出文件打包成一个文件,发送给会计。所有操作都在你的机器上运行:不上传、不需要
账户或 API 密钥,也不会发起任何网络请求。
已收录于 官方 MCP Registry(io.github.theluckystrike/zip-archive-create-extract-bomb-guard)。

@theluckystrike/mcp-zip 的 npm 发布尚待完成,因此今天运行 npx -y @theluckystrike/mcp-zip 会返回 404。在此之前,可使用 .mcpb 一键安装包,或克隆并构建。
安装
Claude Desktop,~/Library/Application Support/Claude/claude_desktop_config.json(macOS)或
%APPDATA%\Claude\claude_desktop_config.json(Windows):
{
"mcpServers": {
"zip": { "command": "npx", "args": ["-y", "@theluckystrike/mcp-zip"] }
}
}
Claude Code:
claude mcp add zip -- npx -y @theluckystrike/mcp-zip
Cursor,.cursor/mcp.json:
{
"mcpServers": {
"zip": { "command": "npx", "args": ["-y", "@theluckystrike/mcp-zip"] }
}
}
工具
| 工具 | 功能 |
|---|---|
zip_create | 将文件或带 glob 模式的目录树打包为新的 .zip |
zip_list | 列出每个条目的大小、压缩后大小和压缩率,并标记其中所有危险内容 |
zip_extract | 解压到目录,并提供路径遍历、符号链接和 zip 炸弹防护以及 dry_run |
zip_add | 将文件添加到已有压缩包 |
zip_extract_text | 直接读取一个文本条目,无需解压任何内容 |
zip_bundle_month | 将相邻服务中的一个月发票、报价单和导出文件打包成一个文件 |
zip_history | 查看你创建过的内容,以及本月免费额度还剩多少 |
license_status, license_activate | 查看 Free 或 Pro 状态,并激活密钥 |
Free 与 Pro
| Free | Pro | |
|---|---|---|
| 每个日历月可创建的压缩包数 | 20 | 无限 |
| 压缩包大小 | 最大 25 MB | 无限 |
| 每个压缩包的条目数 | 最大 200 | 无限 |
读取:zip_list、zip_extract、zip_extract_text | 无限 | 无限 |
| 炸弹、路径遍历和符号链接防护 | 是 | 是 |
读取操作永不计量。免费版限制的是你写入的内容,因为别人发给你的压缩包恰恰是你最需要 在打开前检查的东西,而在安全检查前设置付费墙,就等于在安全检查前设置付费墙。
获取 Pro:https://mcp.zovo.one/buy/zip - 一次性支付 $19,或支付 $39 获得套件中的所有服务,终身使用。 密钥可离线验证;不会向任何地方发送任何内容。
为什么选择 fflate,而不是手写写入器
我们选择了 fflate(纯 JS、零依赖、同步 zipSync/inflateSync),而不是基于 node:zlib 编写 STORE/DEFLATE 写入器;后者完全无需依赖。
无论采用哪种方式,这里都会编写容器格式。此服务会在 src/zipfile.ts 中自行读取中央目录,大约 200 行代码:大小、名称、方法、CRC、外部属性。之所以必须这么做,是因为服务中的每项防护都要在解压任何内容之前,根据这些头信息作出判断;而如果某个库直接返回 {name: bytes},等你查看时,压缩炸弹早已解压完毕。因此,选择库的理由从来不是“它能帮我处理格式”。
剩下的就是压缩器,而这部分不该自己编写。node:zlib 可以做到,但它的原始 deflate 调用以异步为主,每次调用都要经过一次线程池往返;同步调用每次都会创建一个原生流,打包 200 个小文件就要创建 200 个这样的流。fflate 的 deflateSync 是纯 JS 实现,不需要原生句柄;它能在 74 ms 内打包 200 个文件(测量结果见下文),而且意味着这个软件包仍然无需原生构建步骤,这也是整套工具的规则:npx 必须能在任何地方运行。
取舍说明如下:fflate 会在一个缓冲区中构建归档,因此此服务会拒绝超过 512 MB 的输入,而不会假装自己支持流式处理;它也不读取 ZIP64(超过 4 GB 或超过 65,535 个条目),遇到这种情况会明确拒绝,而不是误读。
实测:文件类型无法预测压缩率,重复内容才可以
下表中的每个文件都在这台机器上以第 6 级压缩。 “类型”列是人们对文件的称呼;压缩率则是实际结果。
| 文件 | 类型 | 字节数 | 压缩后 | 比率 |
|---|---|---|---|---|
来自 mcp-pdf 的一份 12 页发票 | 15,125 | 14,118 | 1.07x | |
来自 mcp-docx 的一份含 400 段的合同 | DOCX | 9,897 | 7,311 | 1.35x |
| 4,000 行、数值各异的账单 CSV | CSV | 321,329 | 134,049 | 2.40x |
此服务自己的 index.ts | 源代码 | 39,498 | 11,938 | 3.31x |
package-lock.json | JSON | 138,835 | 33,223 | 4.18x |
| 一份含 20,000 行的应用日志 | 日志 | 1,603,390 | 106,261 | 15.09x |
| 4,000 行账单 CSV,包含 40 个重复的客户端名称 | CSV | 338,549 | 4,094 | 82.69x |
| 50 MB 的零字节 | 炸弹 | 52,428,800 | 51,294 | 1022x |
PDF 和 DOCX 几乎没有压缩效果;查看它们的内部结构后,这并不意外:两者本身就是 deflate 容器,所以再次压缩只是打包,并非压缩。把一个月的发票打包到一个文件里值得这么做,但并不能节省空间。
两行 CSV 的对比很有意思。同一种工具、相同结构、大小相近,压缩率却相差 34 倍:包含 40 个重复客户端名称的文件压缩率为 82.69x,而数值各不相同的文件只有 2.40x。“这是 CSV”无法预测你拿到的文件属于哪一种情况。
实测:为什么压缩炸弹上限设为 100x,而不是 50x
压缩炸弹会因比率超限而被拒绝,直觉上很容易把上限设得较低,远低于零字节文件达到的 1022x。上表说明了为什么这是错误的:一种真实的 CSV 导出文件——zip_bundle_month 从费用跟踪器收集的那类文件——压缩率达到了 82.69x,已达到 100x 上限的 83%,远超 50x。如果把上限设为远低于炸弹压缩率的值,就会拒绝真实的月度导出文件;对方随后便会学着在所有请求中传入 max_ratio,最终导致防护被永久关闭。
因此,比率是第二道防护,而非第一道。第一道防护是总大小:将所选条目声明的未压缩大小相加,并与上限比较(默认为 1 GB,可通过 max_total_mb 修改),因为对于一个整体而言,你可以直接判断是否要接受 199 KB 文件解压为 200 MB,而无需逐个判断条目。两项数据都从中央目录读取,因此拒绝压缩炸弹完全无需解压:
refuse a 500 MB bomb (497.8 KB on disk) 3 ms, nothing inflated, out_dir not even created
实测:有上限的输出缓冲区并不能防范压缩炸弹
fflate.inflateSync(data, { out: new Uint8Array(n) }) 看起来似乎就是完整的解决方案:限制缓冲区大小,就能限制损失。事实并非如此,而且它出问题时悄无声息。将 100,000 字节的条目解压到 10 字节的缓冲区中,会返回10 个字节,且不会抛出任何错误。如果归档头声明一个 100 KB 的条目只有 10 字节,那么提取后就会得到一个 10 字节的文件,并报告成功,截断问题却无从察觉。
因此,缓冲区限制了内存占用,而中央目录中的 CRC-32则验证字节内容。此服务写入磁盘的每个条目都会先与头部进行校验,校验不匹配时就会拒绝该条目并指出其名称。这项检查能将虚假头部导致的静默数据丢失转变为明确报错。
耗时
M 系列笔记本,通过 stdio,每次调用,冷存储:
| 操作 | 实测耗时 |
|---|---|
zip_create,200 个文件,4.0 MB | 74 ms |
zip_list,200 个条目 | 2 ms |
zip_extract,200 个条目 | 47 ms |
zip_extract_text,一个条目 | 1 ms |
| 拒绝一个 500 MB 的压缩炸弹 | 3 ms |
| 整套测试,38 个测试,五个文件 | 3.9 s |
隐私
所有数据都留在你的机器上。此服务完全不含网络代码:没有 fetch,没有 HTTP 客户端,也没有遥测。归档会写入你指定的位置,已创建归档的简要登记信息则保存在 ~/.local/share/mcp-servers/zip/(或 $XDG_DATA_HOME)下。许可证密钥可通过公钥离线验证。
不支持 ZIP 密码,并且传入密码会被拒绝,而非忽略:传统 ZIP 加密已被破解,而 AES ZIP 加密是没有两种工具能达成共识的厂商扩展,因此此处生成“受密码保护”的归档只会构成虚假承诺。
由 theluckystrike 构建。支持邮箱:[email protected]
将这些文档用作 MCP 服务
任何 MCP 客户端(Claude、Cursor、Windsurf、VS Code)都可以通过 GitMCP 直接读取此仓库的文档,无需安装:
- 文档 MCP URL:https://gitmcp.io/theluckystrike/mcp-zip
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。