「Security Code Review Explained」のタイトルカード。コード差分パネルに元の行と変更後の行が表示され、その下に3つのラベル付きステージ:PATTERNS(決定的)、次にPASS、次にREASONING(モデル)。
Guides & Insights

セキュリティコードレビュー解説:レビュアーは差分で何を、なぜ見るのか

著者

Rowan Sterling

公開日

最新モデル · 20すべてのモデルを見る →
ベンチマーク:Artificial Analysis · 毎日更新
すべての記事に戻る

セキュリティコードレビューとは、ソースコードを意図的に読み、作成者が意図していなかった動作をさせられる箇所を見つけることだけを目的とした作業です。この定義は当たり前に聞こえますが、ほとんどのチームが実際に行っているもの、つまり機能レビューの傍らにセキュリティチェックリストを置くやり方と比べると、そうでもありません。OWASP Secure Code Review Cheat Sheet はその境界を的確に示しています。セキュリティレビューが機能レビューと異なるのは、正確さではなく、入力検証、認証、認可、暗号実装、攻撃ベクトルを対象とする点です。完璧に動作する差分でも、攻撃者にシステムへの侵入経路を渡すことはあり、その2つのレビューのうち、それを見つけようとしているのは片方だけです。

この話題が2020年ではなく今、記事にする価値を持つのは、言語モデルが差分をきちんと、低コストで、継続的に読めるようになったからだ。それはレビューの経済性を変えるが、レビューされる次元は一つたりとも変わらない。チェックリストはモデルより古く、動いていない。動いたのは、それをどれだけ頻繁に実行する余裕があるかだ。

レビュアーは実際に何を求めて読んでいるのか

OWASPチートシートは作業を6つの領域に整理しており、このリストの有用な点は、各領域がカテゴリーではなく問いになっていることだ。カテゴリーはチェックを促すが、問いは発見を生む。

Card 'What a reviewer is actually looking for' listing six dimensions - input and injection, authn and session, authorization, cryptography, business logic, configuration and secrets - each with the question it answers about a diff.

入力とインジェクション。 問題は、そのコードにサニタイザーがあるかどうかではなく、何らかのデータがインタープリター——シェル、SQL、テンプレートエンジン、式評価器——に到達するかどうか、そしてその要件がどの層で強制されるべきかということです。パラメーター化クエリを追加する差分は良いものですが、他の呼び出し元が生の文字列を渡している関数にパラメーター化クエリを追加する差分は、問題を移動させただけの差分です。

認証とセッション。 呼び出し元は誰なのか、そしてコードはそれをどうやって特定したのか。繰り返し現れるバグは、パスワードチェックの不具合ではなく、権限変更を生き延びてしまうセッションです。昇格が行われてもトークンは古いクレームを保持したままで、1時間経ってもその権限が残っています。

認可。オブジェクトレベルのチェックを、毎回、すべてのルートで行います。差分で特に注目すべきは、兄弟ルートが持つガードを継承していない新しいルートです。なぜなら、ミドルウェアはルーターごとに登録されるため、別のルーターの下に追加されたルートは単にカバーされないからです。

暗号技術. プリミティブ、モード、鍵長、そして鍵がどこに存在するか。実際の調査でほとんどの発見につながるのは次の2つの問いです。このコードベースを読める者なら誰でも鍵も読めてしまうのではないか、そしてこの比較はタイミングを漏らしてはならないものではないか.

ビジネスロジック。シーケンスが並べ替え可能か、再生可能か、あるいはクライアントが選んだ値によって駆動され得るかどうか。クライアントから送られてきてサーバー側で再導出されない価格、数量、ロール、状態遷移は、どのように検証されていようと指摘対象です。

設定とシークレット。その差分がリポジトリに入れるべきではなかったものを出荷していないか、そしてデフォルト値がコードの実際の実行環境で安全かどうか。デバッグフラグのデフォルトがtrueになっているのは、そのフラグではなく本番環境に関する指摘である。

ベースラインレビュー対差分レビュー

OWASP は 2 つのモードを区別しており、それらを混同することは、無駄な労力と誤った自信の両方を生む一般的な原因です。ベースライン レビューはコードベースを包括的に調査し、新規アプリケーションやメジャー リリース、レガシー システムのオンボーディング、コンプライアンス要件の充足、あるいは何かがすでに問題を起こした後のインシデント後分析に適したツールです。差分ベースのレビューは変更された内容だけを調べ、プル リクエスト、コミット、機能の完成、継続的な検証に適したツールです。

この区別が重要になるのは、両者が異なる作業を生み出すからです。ベースライン・レビューはバックログで終わり、差分レビューはマージ判断で終わります。前者を継続的に実行するのはコスト面で現実的ではなく、後者を、前者を一度も実施したことのないコードベースで実行するのは、チームがカバレッジに対する誤った感覚を積み上げていく原因になります。すべての変更はレビューを通過し、既存の SQL 連結は手つかずのまま残ります。

Screenshot of the OWASP Cheat Sheet Series index entry for Secure Code Review, showing the introduction describing manual examination of source code for vulnerabilities automated tools miss, the baseline-versus-diff review split with their use cases, and a table of contents covering methodology, patterns, techniques, checklists and tools.

テクニックと、それぞれが検出するもの

OWASPは4つのレビュー手法を挙げており、それらは徹底度ではなく、レビュアーがどのような証拠を追うかによって区別されます。 コードパターン分析は、危険な関数呼び出し、信頼できない入力のデシリアライズ、長さチェックの欠落といった見慣れた形を追います。高速であり、決定論的ツールが得意とするまさにその作業です。 データフロー分析は、値が入ってくる場所から使われる場所まで追跡します。これは、3つ前の関数で適用されたサニタイザーがここでもまだ有効かを判断する唯一の方法です。 脅威ベースのレビューは、攻撃者の能力から出発して前向きに進みます。これにより、個々には正しい2つのコンポーネント間の隙間を捉えられます。 ビジネスロジックレビューは、行ではなくワークフローを読み、正当な操作をどのような順序で行うと不正な状態が生じるかを問いかけます。

その4つのうちスキャナが適切に扱えるのは最初の1つだけであり、無誘導のモデルによる処理が適切に機能するのは最初と2つ目だけだ。これはモデルに反対する論拠ではなく、レビュアーにどの手法を望むのかを伝えるべきだという論拠である。なぜなら「セキュリティ上の問題」を求めるプロンプトは、確実にパターン分析を生み出してそこで止まってしまうからだ。

AIが変えたこと、変えなかったこと

AIが作成したコードに関する研究は、レビューのボトルネックを新たに生み出したのではなく、むしろ先鋭化させた。2022年にIEEE S&Pで発表されたGitHub Copilotの提案に関するNYUの研究では、生成されたスニペットの約40%が、18のCWEカテゴリにわたって悪用可能なパターンを含んでいたことが明らかになった。2023年にACM CCSで発表された開発者の行動に関するスタンフォードの研究では、より重大な影響が明らかになった。アシスタントを使用する開発者は、自分のコードが安全であるとより確信していた一方で、測定可能なほど安全性の低いコードを生成していた。より多くの出力とより大きな自信は、レビューの問題である。

レビュアーとしての言語モデルは、その方程式の1つの変数、つまりスループットを変える。すべてのプルリクエストを読むことができ、コストはシート単位ではなくトークン単位でかかり、上記の6つの質問を明示的に尋ねることもできる。それは質問を変えるわけではなく、レビューを信頼できるものにする2つの特性、つまり決定性とコードを実行できる能力を獲得するわけでもない。同じ差分を2回レビューすると異なる指摘が生じることがあり、重大度は実行ごとに変わり、レビュアーは指摘された経路が到達可能であることを証明できない。

Screenshot of the OrcaCode Review product page on OrcaRouter headed 'Open engine. Open prompt. Open bill.', describing a pull-request reviewer whose rules and merge gate run on GitHub under an MIT licence and are billed per token, with an example finding about an idempotency key that still varies in time.

OrcaCode Reviewはそのアイデアを製品化した形であり、設計上の選択が失敗モードを明らかにするため、注意深く見る価値がある。失敗するケースを具体的で再現可能なコメントとして切り出すレビュー——このキーは依然として時間とともに変化するため、再試行された課金は新しいキーを発行し、二重請求になり得る、ここに一行の変更がある——は、レビュアーが行う仕事をしている。「潜在的なセキュリティ問題」と再現手順なしで報告するレビューは、パターンマッチャーより精度の低いパターン分析を行っている。そして、オープンライセンスで公開されたルール・アンド・ゲート・エンジンは、確認する価値のある暗黙の主張をしている。すなわち、レビュアーの判断もまたレビュー可能であるべきだ、という主張だ。

機能する二層配置

決定論的スキャナーと確率的レビュアーを組み合わせるなら、実運用で生き残るのは、それぞれが実際に得意な作業を割り当てる構成だ。スキャナーはプッシュのたびに実行する。数秒で完了し、モデルもばらつきもなく、シークレット、危険な API 呼び出し、安全でないデシリアライゼーション、幻覚的なインポートを検出する。レビュアーはプルリクエストのたびに実行する。数分かかり、モデルを基盤とし、行間のロジックを捉える——認可チェックがフェッチの前に実行されるか、冪等キーが安定した値に紐づいているか、新しいルートがガードを継承しているか。

次に、多くの人が飛ばす層:ゲート。マージをブロックしない指摘は通知であり、通知は金曜日に読まれる。ゲートは狭く、かつ絶対的でなければならない——重大な指摘はブロックし、それ以外はコメントする——そして免除は文書化されなければならない。なぜなら、ゲートの価値は最初の指摘を止めることではなく、すべての回避を可視化することにあるからだ。

コードベースではなく、変更内容をレビューする

差分レビューにおける実践的な規律は短い一連の手順であり、その価値は半日で教えられることにある。差分は、それが何を追加するかという、攻撃面への影響という観点で読み、何を変えるかという観点では読まない。新しいエントリポイントごとに、入力が差分の終わる地点から一歩先までどう流れるかを追う — 脆弱性は通常、その先で呼び出される関数の中にあり、作者はその関数を読んでいない。新しいルートごとに、ガードの登録を確認する。新しい依存関係ごとに、それが存在するか、またその名前を別の誰かが公開していないかを確認する。新しい設定値ごとに、実際にデプロイされる環境で何がデフォルトになるかを問う。

そうしたことのいずれも、言語をよく知っていることを必要としない。だからこそ、セキュリティの専門家ではないレビュアーにも適用範囲を広げられる。ただ、レビュアーがファイルではなく差分を見ていることは必要だ。というのも、この方法全体が、何が新しく追加されたのかを知ることに依存しているからだ。

そして正直な限界はこうです。差分レビューでは、差分が生まれる前から存在していた欠陥を見つけることはできません。アプリケーションにこれまでベースラインレビューが一度も行われていないなら、利用可能な中で最も価値の高いセキュリティ作業は、より優れたレビュアーを用意することではなく、コードベースをお金、アイデンティティ、ファイルアクセスに関わる領域において、上記の6つの問いを用いて意図的に一度通しで見直すことです。その後は、その後に続くすべての差分レビューは、一度は目を通したものを守ることになります。それ以前は、すべての差分レビューは未知のものを守っているのです。