Novu 要的是信心,不是更多流程
- 修复 28 个安全问题
- 前 30 天内
- 83% 的问题
- 需要处理,不是噪音
- NoSQL 注入
- 其他工具都漏掉了
“就像有个渗透测试工程师在审你提的每一个 PR。”
Dima Grossman
首席技术官
关于 Novu
Novu 是一个开源的通知基础设施平台:一套 API 就能通过 15 个以上的渠道(应用内、邮件、短信、推送)发送通知,支持云端部署,也支持物理隔离的私有化部署。开源版本在 GitHub 上有 39,000 个 Star 和 400 多名外部贡献者。Novu 正通过 Novu Connect 拓展双向 Agent 通信,让 AI Agent 直接在 Slack 等渠道中完成任务,而不只是把用户引到别处。
挑战:400 名贡献者参与的代码库,怎么放心
Novu 对每一项外部贡献都执行零信任策略。外部贡献者超过 400 名,任何代码不经严格审查都不能发布。眼下两件事同时发生:AI 让 Novu 交付的代码越来越多,团队也越来越怀疑,为合规而做的第三方安全评估到底能发现什么。
“每年的第三方评估做得越多,我就越不信任它们。他们对所有客户都套同一份十项检查清单,查出来的通常都是些无关紧要的东西。
“该打的勾是打上了,但我们内部根本不信这一套。”
Dima Grossman
首席技术官
Novu 已经有一套分层工具(CodeQL、Greptile、Cursor 的安全审查工具,以及定期的 DeepSec 扫描),在两个节点运行:每次提交 PR 时跑一遍,发版打 tag 前再跑一遍。
“有了 AI,我们在产品面上的产出多了很多。
“审查时人为出错的概率自然也高了很多。”
Dima Grossman
首席技术官
解决方案:流程不变,信心更足
哪些变了、哪些没变,Dima 说得很直接:
“用了 Hacktron,我们的流程一点没变。真正变的只有信心:我们知道自己能抓到复杂得多的漏洞模式。
“有了这份信心,我们也能把速度提上去。”
Dima Grossman
首席技术官
这份信心,说到底来自信号质量。Novu 现有的工具大多只能标出 PR diff 里看得见的问题(Dima 称之为“单跳”利用)。Hacktron 会为仓库构建代码图,并在 PR 之间对比代码图的差异,找出二阶问题:只有追踪一个文件的改动如何影响系统其他位置的代码,这类漏洞才会显现。
“其他工具的评论,很多时候要么不在范围内,要么属于可接受的风险。
“Hacktron 报出来的,团队会认真看、仔细想。很多时候确实很有价值。”
Dima Grossman
首席技术官
Dima 还点出了他一直在防范的风险:噪音疲劳。
“谁都不想让它变成天天喊狼来了的工具。
“报告里通知太多,看着看着就抓不住重点了。”
Dima Grossman
首席技术官
在这里,信号质量不是锦上添花,它决定了团队会认真看这个工具,还是学会无视它。
问题分析
Novu 使用 Hacktron 的前 30 天(2026 年 7 月 6 日至 8 月 6 日):
另有 18 个问题仍待分类处理,还有 1 个因对应的 PR 被放弃而撤回。
能发现哪些漏洞?
Novu 自己的工具大多只能发现单个文件或单个 PR diff 里看得见的问题。Dima 特别看重的,是那些必须跨多个文件追踪调用才能发现的漏洞,而这恰恰是模式匹配扫描器无从标记的。
NoSQL 注入与跨对话越权(高危)
在 PR #12062 中发现,合并前已在同一 PR 中修复。
当时 Novu 正在上线一条新的数据接入链路,让自托管的 AI Agent 向平台发送结构化事件(消息、回复、审批)。链路中有一步需要根据客户端传入的消息 ID,把收到的事件匹配回对应的对话活动:
private async resolveActivityByClientId( environmentId: string, conversationId: string, messageId: string): Promise<ConversationActivityEntity | null> { for (let attempt = 0; attempt < ACTIVITY_RESOLVE_MAX_ATTEMPTS; attempt += 1) { const activity = await this.activityRepository.findOne( { _environmentId: environmentId, identifier: messageId }, '*' ); if (activity) { return activity; } if (attempt < ACTIVITY_RESOLVE_MAX_ATTEMPTS - 1) { await delay(ACTIVITY_RESOLVE_DELAY_MS); } } return this.activityRepository.findByPlatformMessageId(environmentId, conversationId, messageId);}这里有两个问题叠加。第一,查询条件只校验了环境,没有校验活动属于哪个对话。第二,传入的 messageId 直接用进了查询条件,事先没有校验它是不是普通字符串,因此可以被换成 MongoDB 查询操作符,而不是 ID。两者叠加,已认证的调用方就能解析出不属于自己的对话中的活动,进而编辑或删除。
Hacktron Review 追踪了横跨三个文件的调用链,发现了这个问题:接收原始事件载荷的接入控制器,不做深度校验就把载荷转成类型化事件的用例,以及把未校验的 ID 传进上述查询的 sink 服务。
成效:信心足了,交付反而更快
400 多名外部贡献者参与的代码库,如今有了持续审查。没有让团队对安全工具视而不见的噪音疲劳,Novu 也更有信心,交付不降速,反而更快。