本記事では、Python の AST を活用して AI による脆弱性検出を効率化する手法を紹介します。Qiita の @PythonHaru 氏が公開した記事「コードを1行も読ませずに、AIに脆弱性を100%特定させる方法(理論編)」は 530 いいね・471 ブックマークを獲得し、X(旧 Twitter)でも急速に拡散しました。

この記事のポイント

  • AI(LLM)に生のソースコードを読ませるのは、効率の悪い「情報の暴力」(情報量が多すぎて AI が処理しきれない状態)
  • Python の ast モジュールで生成した Deep Structure Map(コードの骨格図)こそ、AI の推論能力を最大化する
  • データの流入から危険地帯への到達をグラフ理論で定義すれば、理論上 脆弱性は100%特定可能

AIコードレビューの限界

GitHub Copilot や ChatGPT にコードをそのまま貼り付けて「脆弱性ある?」と質問する手法は今や一般的ですが、大規模プロジェクトでは2つの致命的な欠陥が生じます。

  1. コンテキストの霧(AI が変数の出自を追跡できなくなる状態)— 数千行のコードを前にした AI は「どの変数がどこから来たか」を見失い、ハルシネーションを起こしやすくなる
  2. トークンの浪費 — コードの「書き方」というノイズに注目してしまい、肝心の「ロジックの破綻」に辿り着く前にリソースを使い果たす

そこで著者は、AI にコードを1行も読ませるのをやめました。代わりに渡したのが、自作の解析コードが抽出した「コードの設計図(Deep Structure Map)」です。

Deep Structure Map:AI に「骨格」だけを渡す

ソースコードは人間が読むための「肉体」ですが、AI が論理推論に必要なのは純粋な「神経系(ロジック)」です。Python の ast モジュールを使い、コードを以下の構造データへ変換します。

DeepAnalyzer クラス(ast.NodeVisitor を継承)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import ast

class DeepAnalyzer(ast.NodeVisitor):
    def __init__(self):
        self.classes = []
        self.functions = []
        self.variables = []
        self.scope_stack = []
        self.call_graph = {}

    def visit_ClassDef(self, node):
        self.classes.append(node.name)
        self.generic_visit(node)

    def visit_Call(self, node):
        # 関数呼び出しをコールグラフとして記録
        self.generic_visit(node)

ast.NodeVisitor を継承した DeepAnalyzer がコード全体を走査し、クラス・関数・変数のスコープ情報とコールグラフを収集します。AI にはこの「関係性の結晶」だけをインプットします。

コードを抽象化して「何がどこに繋がっているか」を事前に定義することで、AI は「3つ前のファイルで定義されたクラスのプロパティ」といった遠い文脈を一瞬かつ正確に把握できるようになります。

理論:なぜ「100%」特定できるのか

グラフ理論における Taint Analysis(汚染伝播解析) を AI に実行させることで、論理的な見落としを原理上なくせます。

脆弱性特定の方程式

脆弱性は以下の3要素が揃ったとき数学的に成立します。

要素役割
Source(汚染源)外部からの入力(API 引数など)が変数に入る
Propagator(伝播ルート)その変数がサニタイズなしに関数間を移動する
Sink(危険地帯)最終的に eval()execute() などの危険な関数に到達する

AI には「SourceからSinkへの導通ルートに欠陥がないか確認せよ」と指示します。その結果、「読書」から解放された AI は「グラフの矛盾探し」という得意分野に専念でき、精度が飛躍的に向上します。

実際の解析フロー

  1. 静的抽出ast.NodeVisitor が全ファイルをスキャンし、変数スコープと関数呼び出しをリスト化
  2. マップ変換 — 解析結果を Mermaid 形式や構造化 JSON に圧縮
  3. AI プロンプト注入 — 「以下の構造マップに基づき、データ汚染ルートを論理的に抽出せよ」と指示
  4. 精密スキャン — AI が「怪しい」と断定した特定の数行だけを最後にチェック

変数スコープの把握(例)

ScopeContext
Instance Variables (self.*)Class: SecurityScanner — found_risks, DANGER_FUNCS
Local / Temp Variables各メソッド内の一時変数

AI はこの表を見るだけで変数の「生存範囲」を完璧に理解できます。

まとめ:AI に必要なのは「肉体」ではなく「地図」

ソースコードをそのまま渡すのは、辞書を丸ごと渡して「間違いを探して」と言うようなものだ。構造マップを渡すのは、「犯行現場の地図」と「監視カメラの記録」を同時に渡すことに等しい。

このアプローチの本質は、AI を「文法の解釈」という低次元なタスクから解放し、「論理の検閲」という高次元な役割にシフトさせることです。

  • 解析コードは陳腐化しない — 実装コードは古くなっても、構造抽出のロジックは AI を永続的に賢くし続ける
  • スケールできる — ファイル数が増えても渡す情報は「圧縮済みの地図」なのでトークン消費が抑えられる
  • 再現性がある — グラフ理論に基づく判定なので、属人的なレビューより一貫性が保てる

本手法の理論的な裏付けを理解したうえで、実装編(続編予定)でどう具体化されるかをあわせて確認することをお勧めします。


参照