请先阅读。 NebuRedaction 是一个实验性项目。它没有达到我们为它设定的准确率目标,不建议用于生产环境,我们也没有继续改进或维护它的计划。我们以 MIT 许可公开思路和代码,希望有人能把它做得更好。
NebuRedaction 的起因
NebuLog 是我们的轻量分布式日志框架,职责是从多个地方收集日志条目,并通过网络发送出去,以便存储和检索。
在和 AI 编程助手 Claude Code 讨论 NebuLog 的部署时,它提醒了一件任何日志系统都绕不开的事:日志消息里绝对不要包含密钥。 密码、API 密钥、令牌,一概不行。助手称之为一项严格的工程纪律。
但这条纪律没有任何东西在执行。NebuLog 是一个出于技术兴趣的项目,没有机制检查这条规矩有没有被遵守。任何人写日志时都可能不小心带进一个密钥;而 NebuLog 的日志要走网络,这样的失误不会只停留在一台机器上。
Frank 最初的想法是让 AI 模型来检查每条日志。当时有两个候选,都不合适。
- Jev(TypeSafe)是一个决策模型,只以专有云服务的形式提供,不能本地部署。检查一条日志,就得先把它发到别人的服务器上。一个必须在数据离开之前完成的检查,自己就不能要求数据先离开。
- Laya(Convai Innovations)是对应的开源方案:4.21 亿参数、Apache-2.0 许可,可以在自己的机器上运行。但它是通用的决策引擎,并非为脱敏训练,而且很重。根据一篇本地部署实践文章,每个检查点的权重约 840 MB,加载后约占 1.7 GB 内存,一次查询在 GPU 或苹果芯片上要几十毫秒。对工作站来说可以接受,对嵌在每个应用里的日志库来说则太重了。
于是思路改变了:不在日志路径上运行 Laya,而是让 Laya 当老师,训练一个专为日志脱敏设计的轻量学生模型。按照 imady 一贯的命名习惯,以 “Nebu” 开头加上用途,这个项目就叫 NebuRedaction。
密钥本身已经成为攻击目标
开发者的密钥通常存放在自己的电脑上:环境变量、配置文件、命令行工具里。这本身就有风险。更麻烦的是,密钥还会以没人想到的方式离开电脑:进入日志,也越来越多地进入与 AI 工具的对话。开发者把报错的命令或配置文件贴给 AI 助手问哪里出了问题,密钥也就跟着发了出去。
这些对话往往不是直接到达 AI 服务商,中间还经过若干层软件,比如 LiteLLM 这样的网关。LiteLLM 是一个开源库,让应用通过统一接口调用多家 AI 服务商,它恰好处在提示词和 API 密钥经过的位置,通常还保存着它所对接的每家服务商的密钥。这类软件包一旦被投毒,恶意版本就拥有与所在应用相同的权限:可以读取这台机器上存放的密钥,再悄悄发送出去。
Frank 的担忧不无道理。LiteLLM 今年已经两次遭到投毒:
- 2026 年 3 月。 恶意版本 1.82.7 和 1.82.8 被发布。据 Help Net Security 援引的研究,这次行动中被盗的数据后来被关联到约 2,500 家机构。
- 2026 年 10 月 21 日。 恶意版本 1.107.0 被发布到 PyPI 和 LiteLLM 的 Docker 镜像上。它在线约两小时。研究人员报告,它会收集云服务凭据、AI 服务的 API 密钥、Git 和 SSH 密钥、浏览器保存的登录信息和 shell 历史,以及 LiteLLM 代理数据库中存放的上游服务商密钥,并发送到攻击者控制的地址。
在这两起已公开的案例中,恶意代码并没有读取对话内容。它在 Python 启动时就开始运行,直接从密钥的存放处窃取:配置文件、凭据存储、shell 历史,以及网关自己的数据库。但道理是一样的:任何处在你数据路径上的软件,以及密钥被复制到的任何地方,都是可能被盗的地方。每一条带着密钥的日志或提示词,都会再多出一个这样的地方。
密钥丢失的后果很少只限于一个系统:
- 攻击者动手很快。 在 10 月的事件中,据 Help Net Security 报道,Wiz 的研究人员观察到攻击者在大约四个半小时内就开始验证被盗的云凭据,并检查能否借此访问 AI 服务。
- 别人花你的钱。 被盗的云服务或 AI 密钥可以在被发现之前,在你的账户上刷出大额账单。
- 一把钥匙打开下一扇门。 代码仓库、数据库或部署流水线的密钥,能让攻击者在企业内部越走越深,甚至给别人依赖的软件投毒,供应链攻击就是这样扩散的。
- 善后很慢。 每一个可能暴露的密钥都要找出来、轮换,并检查是否被滥用过。
解决思路:数据离开之前,先在本地检查
多数机密扫描器是事后运行的,扫描代码仓库或日志归档。对 NebuLog 这样的系统,事后已经太晚:等扫描发现密钥时,那条日志已经穿过网络、被存储,甚至转发给了其他系统。副本已经存在,只能逐个去追。
所以思路是在程序内部、在同一台机器上、在数据离开之前检查,遇到像凭据的内容就遮盖。被遮盖的值形如 ***#a1b2,# 后的四位是原值的简短指纹:你仍能判断两条日志涉及的是否同一个令牌,却无法还原令牌。
同样的逻辑也适用于其他离开程序的内容,包括发往 AI 模型的文本。
传统防范手段的不足
把机密挡在日志之外,常见的做法有三种。每一种都有用,每一种也都有缺口。
- 严守工程纪律。 培训开发者绝不记录机密,并在代码审查时把关。这必不可少,但它依赖每个人每次都做对。机密很少是被故意写进去的,它们往往夹在别的东西里进来:带令牌的网址、调试时打印的配置对象、整套请求头。
- 正则表达式之类的模式规则。 匹配
password、token这类键名,或某云服务商密钥前缀这样的已知格式,gitleaks 等工具就是这样工作的。格式明确时很准,但会把passwordPolicy=strict这类无害值误当成机密,也会漏掉没有固定形状的机密。在我们的评估中,一套典型规则在合成测试集上能找出约 73% 的机密,同时把约 11% 的正常值也标成了机密。 - 信息熵(Entropy)检测。 衡量一串字符看起来有多随机,把像乱码的字符串标出来,detect-secrets 等工具普及了这种做法。它能抓住没有已知格式的密钥,但随机程度是个很单一的信号:一个 32 位十六进制串可能是 API 密钥,也可能只是某个文件的校验值,熵检测分不出来,很容易误伤。
NebuRedaction 的简要原理
NebuRedaction 用一个小型机器学习模型把这些信号结合起来。每个日志属性被转换成一组数字,描述它的键名、值的形状(长度、字符构成、看起来有多随机)以及周围的词。一组小决策树(一种叫梯度提升的技术 [Friedman 2001;Ke 等 2017])对这些数字打分,给出“该值是机密”的概率。
上下文是它胜过单一信号的关键。同一个 32 位十六进制串,键名是 DATADOG_API_KEY 时得分高,被遮盖;键名是 digest 时得分低,原样保留。
模型的判断力是通过知识蒸馏从 Laya 那里学来的:由 Laya 给大量合成样本打标签,再让小模型学着模仿。这项技术早已成熟,我们的补充只是围绕它搭了一套完整、可度量的流程。
最终的模型约 89 KB,离线运行、无依赖,判断一个属性约需 4 到 19 微秒,小到、快到可以放进日志库内部。
NebuRedaction 的适用性和局限性
它为什么而建。 NebuRedaction 检查的是 .NET 或 Python 程序中的结构化日志属性,即带有一些上下文的键和值。它的定位是额外的一层保护,排在良好的纪律和规则之后,绝不能是唯一的一层。
我们没有测试的。 我们是在日志属性上构建和测量它的,没有在 AI 提示词、聊天消息这类自由文本上测过。把它用于提示词是这个思路的自然延伸,但不是我们测量过的结果。
它做不到的。 它不检测姓名、地址、卡号等个人信息,也不在源代码里查找机密。对于已经在同一台机器上运行的恶意代码,它无法保护密钥。针对那种情况的防线是大家熟悉的做法:锁定依赖版本、新版本延后几天再升级、尽量不把机密放在开发者电脑上、出事后快速轮换。
效果如何。 我们在训练任何模型之前就定好了及格线:在 0.1% 误报率下,比纯规则多找出 10 个百分点的机密。我们没有达到。 最好的模型得分 0.804,目标是 0.834。更重要的是,模型学到的是我们自己的数据生成器造出来的格式,而不是“什么是机密”这个一般概念:
- 在训练见过的格式上,误报率为 0.075%;
- 在我们刻意留出、不参与训练的格式上,已发布模型的误报率升到约 49%;
- 在一个由真实开源代码整理的公开凭据数据集上,它只找出约 26% 的凭据。
也有亮点。在“键名叫 password 但值无害”这类刁钻样本上,小模型的误报远少于教它的较大模型;.NET 与 Python 两套实现的结果一致,差异在舍入误差之内。可复用性最高的成果也许是测试方法本身:整族格式留出不练,正是这个设计暴露了模型的弱点。
NebuRedaction 的目的:学习研究,抛砖引玉
NebuRedaction 是一个技术学习和研究项目。我们想弄清楚:一个小到可以放进日志库的模型,能不能学会识别机密;也想完整走一遍从生成数据到如实度量结果的全过程。目前的答案是:还不够好。
我们不会继续这个项目,没有调优模型、增加格式或维护软件包的计划。公开它,是为了分享思路、抛砖引玉,希望有人能把它做得更好。下面几个方向值得尝试:
- 用更多样、更真实的数据训练,而不是生成数据;
- 在提示词和聊天消息上测试这种做法,而不只是日志属性;
- 把模型与规则结合,让两者各补对方的盲区;
- 做一个比我们更好的留出测试。
代码、技术报告和模型都在那里,可以复用、分叉,也可以忽略。
署名、授权与来源
授权。 NebuRedaction 的代码、合成数据生成器、模型权重和文档以 MIT 许可发布,版权所有 2026 Frank Shen。源码见 github.com/imadyTech/NebuRedaction,预发布版软件包 imady.NebuRedaction 已发布到 NuGet。许可文件和完整的第三方声明在仓库中。
致谢。
- Laya(convaiinnovations/laya,Apache-2.0)作为教师模型,其判断被蒸馏进小模型。它只见过合成样本和我们自有的样本,其权重未被重新分发。
- CredData(三星,github.com/Samsung/CredData,Apache-2.0,各文件另受原项目许可约束)仅用于评估,未用于训练,其数据也未被重新分发。
- gitleaks(MIT)、Yelp 的 detect-secrets(Apache-2.0)和三星的 CredSweeper(MIT)作为对比基线与工具使用。两条 gitleaks 规则模式经移植并在仓库中注明出处。
本文提及的产品和公司名称(包括云服务商的密钥格式)均为其所有者的商标,仅用于描述格式或产品。本项目与它们没有任何关联,也未获其认可。
来源。
- Help Net Security:LiteLLM 今年第二次遭供应链攻击,用户被敦促轮换凭据(2026 年 10 月 22 日)
- Datadog Security Labs:LiteLLM 供应链入侵事件解读
- 军舰:Laya 本地部署与集成最佳实践,知乎,2026 年 9 月 28 日。上文关于 Laya 与 Jev 的数字引自该文,并非我们实测。
- NebuRedaction 用户指南与技术报告
- FRIEDMAN J H. Greedy function approximation: a gradient boosting machine[J]. The Annals of Statistics, 2001, 29(5): 1189-1232.
- KE G, MENG Q, FINLEY T, et al. LightGBM: a highly efficient gradient boosting decision tree[C]//Advances in Neural Information Processing Systems 30. 2017: 3146-3154.