☰
Colibrì如何防御恶意模型文件?信任边界设计与内存安全修复深度剖析
2026/10/17 0:28:24 网站建设 项目流程

Colibrì如何防御恶意模型文件?信任边界设计与内存安全修复深度剖析

【免费下载链接】colibriRun frontier MoE models on hardware you already own — pure C, zero deps, experts streamed from disk. Tiny engine, immense model. 🐦项目地址: https://gitcode.com/gh_mirrors/colibri3/colibri

Colibrì 是一个用纯 C 编写、零依赖的 MoE(混合专家)推理引擎,能把 744B 到 2.8T 参数的前沿模型跑在你自己的电脑上,专家权重按需从磁盘流式读取。但"从本地加载别人提供的模型文件"这件事本身就带风险:模型权重可能来自不受信的镜像站,config.json可能被恶意篡改。本文拆解 Colibrì 如何把恶意模型文件当作攻击者输入来防御——它的信任边界设计、"宁可拒绝也不猜测"的加载纪律,以及 v1.6.2 安全版本修复的 6 个内存安全漏洞。

🛡️ 为什么模型文件是最大的信任边界?

多数推理软件默认"本地模型是可信的"。Colibrì 恰恰相反,它在 CHANGELOG.md 中把威胁模型写得明明白白:

Threat model: model files come from mirrors that are not trusted.(威胁模型:模型文件来自不受信任的镜像站。)

对一个需要下载 372 GB 权重、还要解析config.json、safetensors 分片头、甚至服务端 stdin 的引擎来说,攻击者可控的输入有四个入口:

入口攻击面典型风险
模型权重分片伪造的张量字节数、形状、格式堆溢出、越界读写
config.json声明任意维度的 JSON加载期 OOM、空指针解引用
safetensors 分片头伪造 header 长度巨型 malloc
服务端 stdin / HTTP 请求超长 token id、超大请求体越界写、信息泄露

Colibrì 的总原则是:在信任边界处验证,对畸形输入大声拒绝(fail loud),对合法模型零行为变化。下面按数据流从"字节"到"token"逐层看它怎么做到。

第一道关口:容器头部的"门卫"——safetensors 头大小封顶

模型分片文件以 safetensors 格式组织,每个分片开头有一段 JSON 头,声明里面有哪些张量。恶意文件可以在头里声明一个天文数字的hlen,让引擎在读取前就分配巨型内存。

c/st.h 的处理非常直接:

  • 定义ST_MAX_HEADER上限(512 MB)——真实头只有 KB 到 MB 级,超出即拒绝;
  • 多分片场景下,跨分片的重复张量名不再静默"取其一",而是直接拒绝(#1106,v1.7.0 落地),防止伪造头把名字"劫持"到任意分片上。

另外,双 SSD 镜像分片只有在文件大小和 safetensors 头逐字节一致时才会被接受为副本(见 c/st.h 的st_mirror_add注释),不一致的文件自动留在主盘——副本从来不会"半可信"地混入计算路径。

第二道关口:config.json 的有界读取(SEC-9)

config.json决定模型的全部维度:隐藏层大小、层数、专家数、词表……它同样来自不受信目录。修复前的写法是ftell → malloc无上限读取:一个几 GB 的恶意文件就能在加载时打爆内存(OOM),或让malloc失败后的b[got]=0变成空指针解引用。

c/colibri.c 中的cfg_slurp打了三个补丁,代码注释标为SEC-9:

  1. 大小封顶:超过 256 MB 直接拒绝(真实 config 只有 KB 级);
  2. malloc 返回 NULL 检查:失败即返回,不再裸奔解引用;
  3. 要求完整读满:短读(peer 中途断开)视为失败。

其他引擎家族同样执行了这条纪律,例如 c/olmoe.c 对config.json做同样的 256 MB 上限校验,且注释强调"缺失的键曾经是空指针解引用"。

第三道关口:量化格式"拒绝而非猜测"

这是 Colibrì 信任边界里最硬核的一层。量化权重的字节布局(int8 / int4 / int2 / FP8……)在磁盘上只有字节数,格式要引擎自己推断。伪造的容器可以让字节数恰好撞出另一种格式的"签名",诱导引擎用错误方式解码——轻则输出乱码,重则越界读。

c/colibri.c 的裁决规则只有一条:字节数对不上任何一种合法布局 → 打印明确原因并exit(1),注释里反复出现 "refusing (untrusted container)"(拒绝,不受信容器)。

更妙的是它对"字节数巧合"的处理。代码注释(c/colibri.c)把一处真实存在的碰撞称为"设计地雷"(THE DESIGN LANDMINE):GLM-5.2 自己的o_proj张量,其 int8 按行布局的字节数与 FP8 分块布局的签名完全相同。维护者没有一刀切拒绝(那会拒绝一个合法模型),而是建立了"信任 → 验证 → 拒绝"三级路径:

  • 有元数据戳(stamp)且指向唯一候选→ 按戳解析;
  • 戳指向无法消歧的格式→ 按名拒绝;
  • 无戳且形状模糊→ 只解析为"已落盘、可解码"的既有格式,因为写入侧工具已保证不会在该形状下产出歧义容器。

Kimi K3 引擎执行同样纪律:c/kimi_k3.c 对 U8 张量先核对 int8 与 int4-g64 两种布局的精确字节数与 scale 数组规模,两者都不匹配就拒绝加载。

🧨 v1.6.2 安全版本:6 个内存安全漏洞的修复清单

2026-08-14 发布的 v1.6.2 是一个纯安全版本:CHANGELOG.md 记录了六个私下报告的内存安全问题,全部可从攻击者可控输入触达(恶意模型文件 /config.json,或 kimi_k3 的 SERVE stdin)。修复方式统一为"信任边界处验证,合法输入零行为变化":

安全公告(GHSA)位置类型边界修复
GHSA-gf38-c8fx-ppvvkimi_k3 SERVE stdin越界写输入 token 序列在解码前做长度边界校验
GHSA-2qrj-xjmh-mv74c/json.h越界读JSON 解析器按真实缓冲区长度约束
GHSA-w696-h9p7-6rgcinkling 音频路径越界多模态负载按声明形状复核
GHSA-7654-r78q-vc3rdeepseek_v4 索引器越界读/写索引张量形状在批投影前校验
另两则同类模型加载路径越界类全部落在容器解析边界

配合两处更底层的防线:

  • SEC-5:c/colibri.c 中,越界 token id 不会越界读嵌入表,而是填零行返回——"越界 token → 零行,永不越界";
  • SEC-9 之外的形状防护:v1.1.0 的 #413 修复让量化布局必须与磁盘字节数互相验证,形状乘积溢出被拒绝,olmoe 的 dtype-3 路径不再信任伪造的nbytes(那曾是一个堆溢出)。

第四道关口:HTTP 服务端的"失败即关闭"

coli serve/coli web暴露一个 OpenAI 兼容 API,这是引擎唯一的网络面。c/openai_server.py 用SEC-6/7/8三个标记实现了纵深防御:

  • SEC-6(失败即关闭):非环回地址绑定而未配置 API key时,引擎拒绝启动(openai_server.py)——未认证的引擎绝不裸露在网络上;
  • SEC-7(DNS 重绑定防御):_check_host 校验 Host 头。恶意网页可以把域名解析到127.0.0.1从而驱动你的本地服务,这里把 Host 钉死在环回/绑定地址上,其余一律 403;
  • SEC-8(信息泄露收敛):路由遥测等端点未认证一律隐藏(openai_server.py),且认证比较使用hmac.compare_digest恒定时间比对防时序侧信道(openai_server.py);
  • 请求体封顶:read_json强制Content-Length在 1 到MAX_BODY之间,非法直接 400(openai_server.py);
  • 静态资源防路径穿越:仪表盘文件服务用resolve()+relative_to(base)双重校验,../出不了web/dist(openai_server.py)。

🔬 工程层面:用 CI 和校验和兜底

信任边界不是只靠"写对代码",还要防回归:

  • Sanitizer 常设:c/Makefile 提供test-asan目标,用-fsanitize=address,undefined -fno-sanitize-recover=all编译关键解码路径——任何 ASan/UBSan 报告都算失败;
  • 二进制可验证:每次 release 附带SHA256SUMS.txt,下载的引擎能与 CI 从 tag 源码构建的产物逐字节核对(CHANGELOG.md);
  • 本地历史文件也分级:.coli_usage(路由热度历史)只有用户亲手敲路径时才被trusted=1加载,自动发现的同名文件按不受信处理(c/colibri.c)——连"自己目录里的旧文件"都不默认信任。

给普通用户的三条建议

  1. 只从官方 release 下载引擎,并用SHA256SUMS.txt核对,避免"引擎本身被投毒";
  2. 模型权重下载后核对大小(如 GLM-5.2 容器约 372 GB);即便拿到损坏或伪造的容器,Colibrì 也会在加载阶段拒绝并给出具体原因,而不是带着错误格式继续跑;
  3. 局域网共享服务时务必设置 API key,引擎会在无 key 的公网绑定下直接拒绝启动——这是设计保证,不是文档建议。

结语:把"本地文件"当"网络输入"对待

Colibrì 给整个本地推理生态树立了一个少见的设计标杆:用户机器上的一切字节——权重、配置、镜像分片、历史缓存、HTTP 请求——默认来自不受信来源。它不靠加密或签名兜底(模型太大,签名不现实),而是靠一条可审计的工程纪律:每个信任边界处验证、歧义即拒绝、拒绝必须说明原因。对于跑在个人硬件上的 744B 参数巨兽,这比任何华丽的性能数字都更接近"可托付"。🐦

【免费下载链接】colibriRun frontier MoE models on hardware you already own — pure C, zero deps, experts streamed from disk. Tiny engine, immense model. 🐦项目地址: https://gitcode.com/gh_mirrors/colibri3/colibri

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询