
アプリケーションに認証チェックがあっても、それを強制するサービスを呼び出し側が迂回できれば、データが露出する可能性があります。サービスとデプロイ設定が別々のリポジトリにある場合、そのギャップを見つけるには、それらがどのように連携して動作しているかを調べる必要があります。
マイクロサービスのアプリケーションでは、API ゲートウェイと注文サービスが別々のリポジトリにあるかもしれません。ゲートウェイはユーザーのトークンを確認し、そのユーザー ID を注文サービスに渡します。注文サービスはその ID を使って、そのユーザーの注文を返します。呼び出し側が注文サービスに直接到達できる場合、他人の ID を送って、その人の注文にアクセスできてしまう可能性があります。このリスクを評価するには、両方のサービスと、その間のネットワーク設定を調べる必要があります。
// ゲートウェイのリポジトリ
app.get('/orders', async (req, res) => {
const user = await verifyToken(req.headers.authorization);
if (!user) return res.sendStatus(401);
const response = await fetch('http://orders:3000/orders', {
headers: { 'x-user-id': user.id },
});
res.status(response.status).send(await response.text());
});
// 注文サービスのリポジトリ
app.get('/orders', async (req, res) => {
const userId = req.get('x-user-id');
res.json(await getOrdersForUser(userId));
});
私たちは、セキュリティエージェントが検出結果を調査する際に関連リポジトリを利用できるように、CodeRabbit Secure の Deep Scan にマルチリポジトリ分析を組み込みました。この記事では、そのコンテキストをどのように選択するか、スキャン中にエージェントがそれをどう使うか、そしてオープンソースプロジェクトでテストして学んだことを説明します。
スキャン前に関連リポジトリをマッピングする
マルチリポジトリ分析は、コードレビューですでに使っている機能の上に構築されています。CodeRabbit はリポジトリのアーキテクチャサマリーを作成し、それを自動リンク機能と併せて使い、関連するリポジトリを特定します。
セキュリティスキャンが始まる前に、その知識は、スキャン対象のリポジトリにとって有用なコンテキストを提供し得るリポジトリをマッピングするのに役立ちます。認証パスを調査するエージェントは、共有ライブラリやデプロイチャートのコンテキストを必要とするかもしれませんが、組織内のすべてのリポジトリを含めると、無関係な情報が増える可能性があります。自動リンクは、利用可能なコンテキストを密接に関連するリポジトリに絞り込むのに役立ちます。チームは、自分たちの構成に合わせてリンクを設定し、ソースアクセスを調整することもできます。
スキャン中、エージェントは調査の必要に応じて、利用可能なリンク済みソースを探索できます。設定値からそれを読み取るコードを追ったり、共有された実装を調べたり、検出結果に影響するデプロイ設定を探したりできます。ただし、リポジトリを利用可能にしたからといって、その中のすべてのファイルが調査・引用されることが保証されるわけではありません。
Deep Scan はプライマリリポジトリを評価します。リンクされたリポジトリは、その評価のための読み取り専用のコンテキストを提供するものであり、同じスキャンから独自の検出結果やカバレッジを得ることはありません。リンクされたリポジトリ自体を評価するには、そのリポジトリに対して別途スキャンを実行する必要があります。
インフラストラクチャのコンテキストが重要な理由
私たちが Infrastructure as Code (IaC) リポジトリを優先するのは、サービスコードだけでは答えられない疑問に答えられるからです。あるリポジトリは、トラフィックがクラスタの外から到達するかどうかを特定しないまま API ハンドラーを定義しているかもしれず、関連するロードバランサー、Ingress、デプロイ設定は別のリポジトリにあるかもしれません。
それぞれの要素には異なる役割があります。設定ファイルはデプロイが何を宣言しているかを教えてくれ、ソースコードはアプリケーションがその設定にどう応答するかを示します。どちらか一方だけでは、特定の環境でどのリビジョンや設定が動作しているかを証明できません。スキャンでは、リンク済みソースはリンクされたリポジトリのデフォルトブランチ上のコミットに固定されるため、デプロイされているバージョンとは異なる可能性があることに留意してください。
リンク済みコンテキストが各スキャンフェーズを支える仕組み
私たちのセキュリティエージェントは、次のフェーズで動作します。
- Recon(偵察)
- Hunt(探索)
- Verify(検証)
Recon はコードとその周辺についての理解を構築します。Hunt は潜在的なセキュリティ問題を調査します。Verify は候補となる検出結果の証拠と、それが当てはまる条件を精査します。
リンク済みソースは、答えがプライマリリポジトリの外にあるとき、こうした調査の行き先を与えます。エージェントが Recon 中に設定値に出会った場合、その影響を調査する際にリンクされた実装のコンテキストを利用できます。検証の段階では、その値が機密性の高いコードパスに到達するかどうか、あるいは別のコンポーネントが検出結果の条件を変えるかどうかが、重要な問いになることがあります。
このコンテキストをスキャンに取り込むことで、フェーズをまたいだ調査の繰り返しを減らし、開発者が別々のリポジトリから証拠を手作業でつなぎ合わせる手間を省けます。
認証情報を起動コードまで追跡する
私たちは、デプロイチャート、コンテナイメージ、アプリケーションコードを分離しているオープンソースプロジェクトで、マルチリポジトリ分析をテストしました。次の 2 つの実験は、リンク済みコンテキストが結果にどう影響したかを示しています。
1 つ目では、チャートのスナップショットにデフォルトの管理者認証情報が含まれていました。調査では、アプリケーションがそれらの値をいつ使うのかを突き止める必要がありました。
関連するコンテナの起動コードが、欠けていたつながりを補いました。エージェントはチャートの値をエントリポイントまで追い、新規インストール時にその認証情報がアプリケーションのインストールコマンドに渡されることを突き止めました。この詳細により、検出結果には、ブートストラップのパスに関するものだという、より正確な条件が与えられました。
自動リンクを使った 2 回の繰り返しスキャンは、いずれもこのブートストラップの証拠を完全に適用しました。リンク済みコンテキストなしの実行では、この点について部分的な結果にとどまりました。比較対象のすべてのレポートがすでに認証情報の懸念を特定しており、リンク済みコンテキストは、それが当てはまる条件を説明するのに役立ちました。
また、別途ランタイムチェックも実行しました。ブートストラップパスワードの環境変数の値を変更しても、既存インストールのパスワードはローテーションされませんでした。この観察結果が重要だったのは、起動時の値の変更を、すでに作成済みのアカウントのパスワード変更と同等のものとして扱うことを防いでくれたからです。
設定をエンドポイントまでたどる
2 つ目の、より焦点を絞った実験では、呼び出し側が異なる設定のもとでリロードエンドポイントを呼び出せるかどうかを調べました。デプロイチャートはサーバーフラグになる値を定義し、サーバーの実装はどのルートとハンドラーが利用可能かを決めていました。
管理 API を有効にするだけでは、ライフサイクルで制御されるリロードエンドポイントが有効かどうかは分かりませんでした。この問いを解決するには、エージェントはチャートの値をデプロイフラグまで追い、次にランタイムソース内のルートとハンドラーを調べる必要がありました。
関連するランタイムリポジトリを手動で指定した 2 回の繰り返しテストでは、いずれも評価器が有効な設定と無効な設定を正しく区別しました。チャートだけの場合、どちらの答えも未解決のままでした。
ソースアクセスの選択とギャップへの対処
手動モードでは、スキャンはソースアクセスとして選択されたリポジトリのみを読み取れます。何も選択されていない場合、リンク済みソースなしで実行されます。自動モードでは、新たに発見されたものを含むすべての対象リンク済みリポジトリが、ソースリストをカスタマイズするまで、プランの上限の範囲内で読み取り可能になります。発見のプロセスは段階的に進むため、リストが揃うまでに時間がかかることがあります。
CodeRabbit は、スキャンの開始時にアクセスを再確認します。選択したソースが利用できない場合や、分析中に準備できない場合でも、スキャンは手元にあるコンテキストで続行できます。
Deep Scan は、GitHub Cloud、GitHub Enterprise Server、GitLab Cloud でリンクされたリポジトリを利用できます。
つながったコンテキストから実用的な検出結果へ
検出結果は、開発者がその背後にある条件を理解できるとき、より有用になります。関連するソースは、疑わしい値をそれを利用するコードに、あるいはデプロイ設定をそれが有効にするルートに結びつけるのに役立ちます。これにより、チームは検出結果を評価し、何を調査し何を変更するかを判断するための、より多くの情報を得られます。
それでもスコープは重要です。Deep Scan はプライマリリポジトリについての検出結果を報告し、リンク済みソースはその作業を支える証拠を提供します。検出結果がリンク済みソースを引用する場合、CodeRabbit はそのリポジトリ、ファイル、固定されたコミットをコンテキストの証拠として表示できます。
Deep Scan のリンク済みリポジトリを設定し、スキャンがアクセスできるソースを確認して、あなたのリポジトリでスキャンを実行してみてください。


