Hacktron が Novu のセキュリティチームにもたらしたのは、プロセスの追加ではなく確信
- 28 件のセキュリティ問題を修正
- 最初の 30 日間で
- 検出結果の 83%
- ノイズではなく、対応が必要なものでした
- NoSQL インジェクション
- 他のツールが見逃していたもの
「まるで、すべての PR をペンテスターがレビューしてくれているようです。」
Dima Grossman
CTO
Novu について
Novu は、オープンソースの通知インフラプラットフォームです。15 以上のチャネル(アプリ内、メール、SMS、プッシュ)に通知を送る単一の API を提供し、クラウドとエアギャップ環境のオンプレミスの両方で導入されています。このプロジェクトは GitHub で 39,000 個のスターを獲得し、オープンソース版には 400 人以上の外部コントリビューターがいます。現在は Novu Connect による双方向のエージェント通信へと領域を広げており、AI エージェントがユーザーを別の場所に誘導するだけでなく、Slack などのチャネル内で直接タスクを完了できるようにしています。
課題:400 人のコントリビューターが関わるコードベースを信頼する
Novu は、外部からのすべてのコントリビューションにゼロトラストのポリシーを適用しています。外部コントリビューターが 400 人を超えるため、精査なしに出荷されるものはありません。そして今、2 つのことが同時に起きています。AI によって Novu が出荷するコードの量が増えていること、そしてチームが、コンプライアンス目的のベンダーによるセキュリティレビューが実際に何を見つけられるのかに懐疑的になっていることです。
「年次のベンダーレビューを重ねるほど、それを信頼できなくなっています。彼らはどの顧客企業にも 10 項目のプレイブックを当てはめるだけで、たいていはかなり的外れなものを見つけてきます。」
「チェックマークは埋まりますが、社内ではまったく信頼していません。」
Dima Grossman
CTO
Novu はすでに多層的なスタック(CodeQL、Greptile、Cursor のセキュリティレビュアー、定期的な DeepSec スキャン)を、すべての PR の提出時と、リリースのタグ付けの前という 2 つのチェックポイントで実行しています。
「AI によって、プロダクトの対象領域という点で、より多くの成果を生み出せるようになっています。」
「当然、そのぶんレビュー時のヒューマンエラーの要因もずっと大きくなります。」
Dima Grossman
CTO
Hacktron の役割:プロセスの変更ではなく、確信
Dima は、何が変わり、何が変わらなかったかについて率直に語りました。
「Hacktron を導入しても、私たちのプロセスは何も変わっていません。本当に変わったのは、確信の度合いだけです。はるかに複雑なパターンまで捕捉できているとわかっていることです。」
「そしてその確信が、開発のスピードを上げることにもつながります。」
Dima Grossman
CTO
その確信は、シグナルの質によるものです。Novu の既存のツールが指摘するのは、主に PR の差分から見える問題です(Dima はこれを「ワンホップ」のエクスプロイトと表現しました)。Hacktron はリポジトリのコードグラフを構築し、PR ごとにそのグラフの差分を取ることで、二次的な問題を提示します。つまり、あるファイルの変更がシステムの別の場所にあるコードにどう影響するかをたどって初めて見えてくる脆弱性です。
「他のツールからのコメントは、多くの場合スコープ外か、許容できるリスクです。」
「Hacktron からの指摘があると、チームは注意を払ってよく考えます。多くの場合、かなり的を射たものだとわかります。」
Dima Grossman
CTO
Dima は、自身が積極的に対策しているリスクとして、ノイズ疲れも挙げました。
「オオカミ少年のようになってほしくはありません。」
「レポートの通知があまりに多いと、肝心な点を見落とすようになります。」
Dima Grossman
CTO
ここでは、シグナルの質は「あればうれしい」程度のものではありません。チームが実際に読むツールになるか、無視することを覚えてしまうツールになるかの分かれ目です。
検出結果の分析
Novu が Hacktron を使い始めて最初の 30 日間(2026 年 7 月 6 日~8 月 6 日)の結果は次のとおりです。
18 件の検出結果はまだトリアージ待ちです。さらに 1 件は、元の PR が破棄されたため取り下げられました。
どのような脆弱性を見つけますか?
Novu 自身のツールが主に捕捉するのは、単一のファイルや単一の PR の差分で見える問題です。Dima が価値があると挙げた検出結果は、複数のファイルにまたがって呼び出しをたどって初めて現れるもの、まさにパターンマッチング型のスキャナーでは指摘しようのない類いのものです。
NoSQL インジェクションと会話をまたぐ認可バイパス(重大度「高」)
PR #12062 で検出され、マージ前に同じ PR 内で修正されました。
Novu は、セルフホストの AI エージェントが構造化イベント(メッセージ、返信、承認)をプラットフォームに送信するための、新しい取り込み経路を展開していました。このパイプラインの一部では、クライアントが指定したメッセージ 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);}ここでは 2 つの問題が重なっていました。まず、クエリのフィルターは環境しか確認しておらず、アクティビティがどの会話に属しているかを確認していませんでした。次に、受信した messageId は、そのフィルターで直接使われる前にプレーンな文字列として検証されていなかったため、ID の代わりに MongoDB のクエリ演算子に置き換えられる可能性がありました。この 2 つが組み合わさることで、認証済みの呼び出し元が、自分のものではない会話に属するアクティビティを特定し、さらに編集や削除をすることができました。
Hacktron の Review は、3 つのファイルにまたがる呼び出しチェーンをたどることでこの問題を捕捉しました。生のイベントペイロードを受け取る取り込みコントローラー、それを深い検証なしに型付きイベントへキャストするユースケース、そして検証されていない ID を上記のクエリに渡すシンクサービスです。
結果:遅くではなく、速く出荷するための確信
Novu は、400 人以上の外部コントリビューターが関わるコードベース全体で継続的なレビューを受けています。チームがセキュリティツールを読まなくなる原因となるノイズ疲れはなく、出荷のスピードを落とすのではなく上げられるだけの確信を得ています。