1. はじめに:AI監査ログの信頼性問題と解決の方向性

AIエージェントの監査ログには、構造的な信頼性の課題が存在する。エージェントが行動主体であると同時にログの作成者でもあるため、証人と疑わしい主体が同一になってしまうという指摘がある(The Witness Was the Suspect)。従来のシステムログでは、アプリケーションコードがログを書き込み、そのコードは人間がレビュー・テストしてきた。しかしAIエージェントの場合、ログの内容を生成しているのはエージェント自身の推論プロセスであり、人間が事前に変換可能性を検証したわけではない。ログの内容そのものが、監査対象である主体の「主張」に過ぎない。

この状況下で従来の「内容の真偽を検証する」アプローチを採用すると、検証者自身も信頼できるかどうかという問いが生じ、検証の検証の検証と無限に再帰的な検証が必要になる可能性がある(The Witness Was the Suspect)。この無限再帰を回避するためには、検証の軸を「記録された内容が正しいか」から「記録が作成以降改竄されていないか」へ転換する設計判断が必要である。真実性を証明するのではなく、誰がいつ何を主張したかを改竄不可能な形で記録し、改竄痕を可視化することが設計の目的になる(The Witness Was the Suspect)。

本記事では、NoireBoxの設計思想を参考に、エージェントの意思決定フローを不変な形で記録し、外部検証可能な監査基盤を構築するパターンを提示する。重要なのは、完全な信頼を担保することではなく、改竄を試みた痕跡を検知できる仕組みを備えているかどうかである。この設計思想を踏まえた上で、実装レベルの判断基準と落とし穴まで踏み込んで解説する。

2. 前提:エージェント監査の技術的課題と設計要件

AIの失敗は明確なエラー出力を持たず、「妥当に見える(plausible)」形式で発生することがある(The Witness Was the Suspect)。例外がスローされず、ログレベルもINFOのまま、出力形式も正しく、内容だけが微妙にずれている場合、従来のログ監視が「ERRORレベルの出現」や「タイムアウト」をトリガーにしている限り、こうした失敗は検知されない。つまり、監査ログの役割は「システムが正しく動作したことを証明する」ことではなく、「誰がいつどのような決定を下したかの履歴を改竄不能にする」ことにある。

この要件を満たすには、二つの技術的ギャップを埋める必要がある。第一に、内部担当者が日付や内容を後から改竄できるギャップ。アプリケーションの内部時計は管理者権限で書き換え可能であり、ログ内のタイムスタンプ自体が信頼できない場合がある。このギャップを埋める手法の一つとして、RFC 3161準拠のTSA(タイムスタンプ局)による外部アンカーが挙げられる(ADR 019)。第二に、ログの整合性を暗号学的に検証するギャップ。単にログファイルを保持しているだけでは、1エントリだけ差し替えられたことを検知できない。ハッシュチェーンにより、任意の位置での改竄が後続すべてのハッシュ値の不一致として現れるように設計する。

ここで設計上の判断基準を整理しておく。監査ログの「不変性」と「内容の真偽」は別問題である。不変性は暗号学的に検証可能だが、真偽はコンテンツ検証層(ガードレールや人間によるレビュー)の領域である。この二層を混同すると、ログが改竄されていないのに内容は虚偽であるという状況に対処できなくなる。後述するNoireBoxの設計思想は、この境界線を明確に引きながら不変性だけを担保するという点で、従来の「全信頼型」ログ設計と本質的に異なる。

3. NoireBoxの設計思想:ハッシュチェーンとEd25519署名による封じ込め

NoireBoxは、AIエージェントの意思決定をハッシュチェーンで連結し、Ed25519署名により作成者を証明する「フライトデータレコーダー」として機能するとされている(NoireBox)。航空機のブラックボックスが、墜落原因を証明するのではなく、墜落直前のパラメータが改竄されていないことを保証するのと同じである。エージェントの各意思決定イベント(入力、推論ステップ、出力)がチェーン上に追加され、各ノードは前ノードのハッシュ値を含むため、中間の任意のノードを改竄すると後続すべてのハッシュが不一致になる。

Ed25519署名の役割は、ハッシュチェーンの「誰が書いたか」を固定することである。ハッシュチェーンだけでは改竄検知は可能だが、作成者の帰属は証明できない。署名を付与することで、特定のプライベートキーで署名されたイベントであることをパブリックキーで検証可能にし、後から「そのイベントは自分ではない」と否認できない状態を作る。この二層(不変性+帰属性)が組み合わさって、監査ログの信頼性を構成する。

ただし、このアプローチが保証するのは「記録が作成以降改竄されていないこと」と「作成日時」であり、記録内容の真偽までは証明しない(NoireBox)。NoireBoxは「お守り」ではなく「道具」である。エージェントが悪意を持って正しい手順で偽の情報を出力した場合、ログは完全に不変であり署名も有効だが、内容は虚偽である。この限界を理解した上で、コンテンツ検証層を別途設計する必要がある。監査ログ設計において重要なのは、完全な信頼ではなく、改竄を試みた痕跡を検知できる仕組みを備えているかどうかである。

flowchart LR
    A["意思決定イベント"] --> B["ハッシュ計算"]
    B --> C["前イベントハッシュと連結"]
    C --> D["Ed25519署名付与"]
    D --> E["チェーン更新"]
    E --> F["TSA外部アンカー"]

4. 実装パターン:ガードレールと認証の設計判断

ガードレールの3段階構成

NoireBoxのガードレールは、処理コストの低い順に正規表現、MLマイクロモデル(293KB)、LLMジャッジの3段階で構成されているとされる(ADR 019)。この設計の根底にある判断は、すべてのイベントを最上位のLLMジャッジに通すことの非効率性である。LLMジャッジは精度が高いが、呼び出しコストとレイテンシが実運用のボトルネックになる可能性がある。一方、正規表現は処理コストがほぼゼロだが、検出できるパターンが限定的だ。

3段階にすることで、大部分のイベントを低コストな層で処理し、疑わしい場合のみ上位層にエスカレーションするファネル構造が生まれる。設計上の重要な判断点は、各層の閾値設定である。正規表現層で検出されたパターンをそのままML層に渡すのか、それとも正規表現層で即座にブロックするのか。この判断は、誤検出率(False Positive)と漏検出率(False Negative)の許容範囲によって決まる。コンプライアンスが優先される環境では、誤検出を許容して上位層に多くエスカレーションする設計が適切であり、リアルタイム性が重視される環境では逆の設計が選ばれる。

手法コスト精度制約・注意点
正規表現最小パターン依存新規攻撃パターンへの追従が遅い
MLマイクロモデル(293KB)小中モデル更新時の再デプロイが必要
LLMジャッジ大高レイテンシ・APIコストが実運用の制約
Meta Prompt Guard 2中高英語のみ・ライセンス制限・依存が重い

外部ソリューションの採用判断

ガードレールの実装において、既存の外部ソリューションをそのまま採用する選択肢も検討される。NoireBoxではMetaのPrompt Guard 2が候補に上がったが、最終的に採用を見送ったとされている。見送りの理由は3点ある。第一に、言語対応が英語のみであること。日本語を含む多言語環境ではそのままでは使えない可能性がある。第二に、ライセンスが制限されていること。商用利用や改変の自由度が確保できない場合、長期的な運用リスクになる。第三に、依存関係が重いこと。既存スタックとの整合性を保ちつつ導入コストを抑えるという設計制約と矛盾する(ADR 019)。

この判断プロセス自体が設計判断の典型案例である。外部ソリューションの採用は「作らない」ことよりも「維持できない」リスクを伴う。ライセンス変更、メンテナンス終了、依存ライブラリの破壊的変更といった要因は、導入後に突然発生する可能性がある。独自実装のコストと外部依存のリスクを比較し、後者の方が大きいと判断した場合は、規模が小さくても独自実装を選ぶべきである。

認証設計とサイドチャネル対策

NoireBoxのOAuth2認証は任意の有効化が可能であり、未設定時はローカルデモ用にAPIがオープンになる場合がある(ADR 019)。この設計は開発体験とセキュリティのトレードオフを意図的に取ったものである。本番環境では認証を有効化し、APIへの無認可アクセスを遮断する必要がある。

認証実装において見落としがちなのが、シークレット比較の処理である。通常の等値比較演算子は、文字列の先頭から1文字ずつ比較するため、一致する文字数に応じて処理時間が変わる。この時間差を計測することで、攻撃者はシークレットの先頭部分を手探りで特定できる(タイミング攻撃)。NoireBoxではこの対策として定数時間ロジックを用いており、比較結果が一致するか否かに関わらず処理時間が一定になるようにしている。この処理は実装上の細部に見えるが、監査ログAPIが認証情報を扱う以上、サイドチャネル攻撃の入口になり得るため、見逃してはならない。

5. 不変性の担保:RFC 3161準拠TSAによる外部アンカー

内部タイムスタンプの限界

ハッシュチェーンとEd25519署名によって、記録の改竄検知と作成者の証明は実現できる。しかし、タイムスタンプについては根本的な制約が残る。内部システムが記録した日時情報は、システムにアクセス権を持つ者が後から書き換えることができる。具体的には、OSのシステムクロックを巻き戻す、あるいはログファイルのメタデータ(mtime)を直接編集することで、イベントの発生時刻を偽装できる。これは暗号学的な仕組みでは防げない。なぜなら、タイムスタンプはデータの一部としてチェーン内に格納されており、チェーンの整合性検証は「このハッシュはこの時刻に生成された」とは証明しないからである。

このギャップを埋めるために、NoireBoxではRFC 3161準拠のTSA(タイムスタンプ局)を用いて、チェーンの頭部ハッシュを外部にアンカーしているとされる(ADR 019)。TSAは独立した第三者機関が運用するサービスであり、クライアントが送信したハッシュ値に対して、TSAが自らの証明書で署名したタイムスタンプを返す。このタイムスタンプは、TSAの公開鍵で検証可能であり、内部システムからは改竄できない。

TSAアンカーの設計判断

TSAへのアンカーは、チェーンの全イベントに対して行う必要はない。コストと運用の簡便性を考慮し、チェーンの頭部(最新のブロック)ハッシュに対して一定間隔でアンカーする設計が現実的である。アンカー間隔の設計判断は、許容される改竄の検知遅延時間に依存する。間隔を短くすれば検知精度は上がるが、TSAへのリクエスト頻度が増えコストが上がる。逆に間隔を長くすればコストは抑えられるが、アンカーとアンカーの間に改竄が発生した場合、その区間内のイベントは「改竄されていない」とは証明できない。

TSAサービスの選定基準としては、第一に信頼できる第三者であること(公開鍵基盤の信頼性、運用実績)、第二にコストと可用性のバランスが挙げられる。TSAが利用不能な期間が発生した場合、その間にアンカーされない区間が生まれる。このリスクを許容できるかどうかが、選定時の重要な判断材料になる。

sequenceDiagram
    participant A as エージェント
    participant B as ハッシュチェーン
    participant C as TSA
    participant D as ブロックチェーン
    A->>B: 意思決定イベントを記録
    B->>B: 頭部ハッシュを計算
    B->>C: 頭部ハッシュをTSAに送信
    C->>C: RFC 3161準拠のタイムスタンプを付与
    C-->>B: 署名付きタイムスタンプを返却
    B->>D: タイムスタンプ付きハッシュをブロックチェーンに記録
    D-->>B: 取引ハッシュ(取引ID)を返却

6. 出力形式:機械向けJSONと人間向けPDFの二重構造

二重構造の設計意図

監査ログの消費者は単一ではない。自動化された監視システムやCI/CDパイプラインは構造化データとしてJSONを消費する一方、コンプライアンス審査や規制当局への提出では、人間が直感的に内容を把握できる形式が求められる。NoireBoxでは、JSON形式で機械向けの証明を提供しつつ、reportlabを用いてA4サイズのPDFアテスタションを生成し、人間向けのコンプライアンス対応も可能にしている(ADR 019)。

この二重構造の設計判断は、「同じデータを異なる形式で出力する」のではなく、「異なる目的に対して異なる情報密度で提示する」点にある。JSONにはハッシュ値、署名、チェーンインデックス、イベントメタデータといった機械が検証に必要な完全な情報を含める。一方、PDFアテスタションには、監査担当者が「改ざん痕の有無」を視覚的に確認できるレイアウトを設計する。具体的には、チェーンの整合性検証結果(正常/異常)、TSAタイムスタンプの有効性、署名検証結果を要約した表形式で提示し、異常がある場合は該当イベントをハイライトする。

JSON出力の構造設計

JSON出力の設計において重要なのは、検証に必要十分な情報だけを包含し、余計なフィールドを含まないことである。検証者がJSONを受領した時点で、外部の情報を参照せずに整合性を検証できるようにする。以下は、検証に必要な最小限のフィールドを含むイベントレコードの構造例である。

{
  "event_id": "evt_20240101_001",
  "timestamp": "2024-01-01T12:00:00Z",
  "agent_id": "agent-01",
  "action": "decision",
  "payload": {
    "input_hash": "sha256:a1b2c3...",
    "output_hash": "sha256:d4e5f6..."
  },
  "prev_hash": "sha256:0000000000000000000000000000000000000000000000000000000000000000",
  "current_hash": "sha256:f7a8b9...",
  "signature": "ed25519:base64encoded...",
  "tsa_anchor": {
    "timestamp": "2024-01-01T12:00:01Z",
    "serial": "1234567890",
    "status": "valid"
  }
}

この構造では、prev_hashとcurrent_hashの整合性、signatureのEd25519検証、tsa_anchorのTSA証明書による検証の3点を確認することで、そのイベントがチェーンの一部として改ざんされていないことを証明できる。PDFアテスタションは、この検証結果を「正常」または「異常(該当イベントID付き)」として可視化するレイヤーであり、JSONの代わりではなく補完として機能する。

7. 実装手順:ハッシュチェーンの構築と署名検証

ハッシュチェーンの構築は、各イベントの作成時に「前イベントのハッシュ値を現イベントに埋め込む」ことで、任意の位置での改ざんを検知可能にする仕組みである。ここで設計判断が分かれる点は、ハッシュの計算対象をどう定義するかである。

計算対象に含めるべきフィールドは、少なくとも timestamp、data(エージェントの行動内容)、prev_hash の3つである。current_hash 自体を計算対象に含めると自己参照になり構造的に破綻する。signature も計算対象に含める必要はなく、これは計算対象の外部に付随する検証手段として分離する。この分離により、ハッシュの再計算と署名検証を独立に実行でき、どちらか一方が壊れていれば改ざんと判定できる。

import hashlib
import json
import time
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey

private_key = Ed25519PrivateKey.generate()
public_key = private_key.public_key()

def create_event(prev_hash: str, data: dict) -> dict:
    event = {
        "timestamp": time.time(),
        "data": data,
        "prev_hash": prev_hash,
    }
    payload = json.dumps(event, sort_keys=True).encode()
    current_hash = hashlib.sha256(payload).hexdigest()
    event["current_hash"] = current_hash
    event["signature"] = private_key.sign(payload).hex()
    return event

def verify_event(event: dict) -> bool:
    payload = json.dumps({
        "timestamp": event["timestamp"],
        "data": event["data"],
        "prev_hash": event["prev_hash"],
    }, sort_keys=True).encode()
    if hashlib.sha256(payload).hexdigest() != event["current_hash"]:
        return False
    try:
        public_key.verify(bytes.fromhex(event["signature"]), payload)
    except Exception:
        return False
    return True

この実装で注意すべきは、JSONのシリアライズ順序である。sort_keys=True を指定しないと、同じ内容でもキーの順序が異なるとハッシュ値が変わり、検証が失敗する。シリアライズの正規化ルールを定義し、作成側と検証側で完全に一致させることが前提条件となる。

チェーンの状態遷移を整理すると、以下のようになる。各イベントの追加は、ハッシュ計算→署名付与→TSAアンカーの3ステップを順に経て、初めてチェーンに組み込まれる。

stateDiagram-v2
    state "待機中" as A
    state "ハッシュ計算" as B
    state "署名付与" as C
    state "TSAアンカー" as D
    A --> B : イベント受信
    B --> C : ハッシュ確定
    C --> D : 署名完了
    D --> A : チェーン更新

TSAアンカーのステップで外部往復が発生するため、ネットワーク遅延がチェーンの追加速度に制約をかける。実務上は、TSAの応答を待たずに署名済みのイベントをローカルに暫定保存し、TSAの応答が到着してから正式に確定させる非同期方式を採用するのが現実的である。この場合、暫定保存中のイベントは「未確定」として扱い、外部から参照されないようにアクセス制御をかける必要がある。

8. 落とし穴:改竄検知と内容検証の境界線

NoireBoxの設計思想を正しく理解するための最大の障壁は、「改ざんされていない」ことと「記録された内容が真実である」ことを混同することである。これは技術的な問題というより、監査の目的設定における根本的な誤解である。

具体的には、エージェントが悪意を持って正しい手順で偽の情報を出力した場合を想定する。エージェントが「ユーザーは承認した」という偽のイベントを、ハッシュチェーンに正しく連結し、Ed25519で正しく署名し、TSAにも正しくアンカーしたとする。このとき、チェーンの整合性は完全に保たれており、改ざん検知の観点からは「正常」である。しかし記録された内容は虚偽である。NoireBoxは記録が作成以降改ざんされていないことと作成日時を証明する道具であり、記録内容の真偽までは証明しない(NoireBoxのREADME)。

この境界線を設計に反映するためには、監査ログの役割を2層に分離する必要がある。1層目はNoireBoxが担う「不変性保証」であり、記録が改ざんされていないことを暗号学的に証明する。2層目は別途設計すべき「コンテンツ検証」であり、記録された内容が業務的に妥当かを判断する。2層目の手法は、ガードレール(正規表現・MLマイクロモデル・LLMジャッジ)による出力の妥当性チェックや、人間のレビュー、あるいは外部データソースとの突合などが考えられる。

この2層を混同すると、2つの失敗パターンが生じる。1つ目は、不変性保証だけで「監査は完了した」と判断し、虚偽の記録を鵜呑みにしてしまうこと。もう1つは、コンテンツ検証に失敗したイベントを「改ざんされた」と誤認し、本来はエージェントの判断ミスである問題をセキュリティインシデントとして過剰対応してしまうこと。監査結果の解釈には、この2層が何を証明し何を証明しないかを明確にしたうえで、人間の判断と追加的な調査プロセスが不可欠である。

9. 運用:監査ログの監視とインシデント対応

ハッシュチェーンが構築されただけでは、改ざんが実際に起きた瞬間に検知・対応する運用プロセスがなければ意味をなさない。運用設計の中心となるのは、チェーンの整合性を継続的に検証する監視ループである。

監視ループは3つのチェックを定期的(またはリアルタイムで)実行する。1つ目はチェーンの連続性チェックであり、各イベントの prev_hash が前イベントの current_hash と一致するかを確認する。2つ目は署名検証であり、各イベントの signature がパブリックキーで検証可能かを確認する。3つ目はTSAアンカーの整合性チェックであり、チェーンの頭部ハッシュがTSAに提出されたものと一致するか、TSAの証明書が有効期限内かを確認する(ADR 019)。

いずれかのチェックが失敗した場合のインシデント対応手順は、以下の順序で進める。まず、該当エージェントの実行を即時停止し、さらなるイベントの追加を遮断する。次に、失敗したチェックの位置(どのイベントIDから整合性が崩れているか)を特定し、その前後のイベントを隔離された環境でフォレンジック調査する。このとき重要なのは、隔離環境でチェーンの再検証を行い、改ざんの範囲(単一イベントか、連続する複数イベントか)を確定することである。範囲が確定するまで、そのエージェントの生成した全出力を信頼しないという原則を堅持する。

TSAアンカーの運用面では、TSAサービス自体の可用性がチェーンの信頼性に直結する点に注意が必要である。TSAが停止している間、チェーンの頭部ハッシュが外部にアンカーされないため、その期間に内部で改ざんが行われた場合、外部検証では検知できない。このギャップを埋めるため、TSAへの提出を定期的(例:チェーンの各Nイベントごと)に実行し、提出の遅延が閾値を超えた場合にアラートが発生する仕組みを備える。誰がいつ何を主張したかを改ざん不可能な形で記録し、改竄痕を可視化することが監査の目的である以上(監査ログの信頼性に関する分析)、外部アンカーの欠如自体がインシデントとして扱われるべきである。

保管期間とストレージコストのバランスについては、チェーンの性質上、過去のハッシュ値に依存するため、中間のイベントを削除するとチェーンが断裂する。この制約を踏まえ、一定期間(規制要件に準拠)を超えたチェーンの末端を、TSAで封じ込めた後にアーカイブに移行する戦略が現実的である。アーカイブ後もTSAアンカーにより不変性は維持されるため、ストレージコストを抑制しながら監査可能性を保持できる。

10. 発展:マルチエージェント環境での監査設計

単一エージェントの監査が成立した時点で、次の課題はエージェント間の相互作用の追跡である。複数のエージェントが連携する環境では、各エージェントが自前のハッシュチェーンを持つだけでは不十分だ。エージェントAがエージェントBに権限を委譲し、BがCにプロンプトを受け渡したようなケースでは、各チェーンは個別に整合的であっても、全体としての因果関係が追跡不能になる。

クロスエージェントイベントのチェーン統合

この問題に対する設計判断として、エージェント間のやり取り自体をイベントとしてチェーンに含める手法が考えられる。具体的には、エージェントAがBへメッセージを送信した時点で、Aのチェーンに「送信イベント」を記録すると同時に、Bのチェーンに「受信イベント」を記録する。両イベントには共通の相関IDを付与し、後から対応付けられるようにする。これにより、単一のチェーン内部だけでなく、チェーン間の因果関係も検証可能になる。

権限委譲の場面では、委譲元の署名と委譲先の署名の両方がイベントに記録される。これにより、BがAの権限で行動したことを後から証明でき、権限の濫用があった場合にどのエージェントがどの時点で権限を行使したかを特定できる。プロンプトの受け渡しについても、受け渡した時点のハッシュ値を記録しておくことで、中継過程で内容が変えられたかどうかを検知できる。

ゼロ知識証明による将来の拡張

マルチエージェント環境では、監査時にすべての中間データを開示する必要がなくなる場合がある。例えば、金融機関のAIエージェントが顧客の機密情報を処理する際、監査当局に「処理が整合的だった」ことを証明しつつ、処理内容そのものは開示したくないという要請が生じる。ゼロ知識証明(ZKP)を用いれば、証明対象のデータを第三者に開示せずに、チェーンの整合性や署名の有効性を検証する技術的基盤となる。現時点では実装コストが非常に高いため、設計段階でインターフェースを確保しておくことが現実的な対応である。

11. まとめ:信頼できるAIシステムのための監査基盤設計

AIエージェントの監査ログが抱える根本的な課題は、行動したエージェント自身がログを書き込むという構造にある。証人と疑わしい主体が同一である以上、ログの「内容の真偽」を検証するアプローチは無限の再帰に陥る可能性がある。この問題に対する解決策は、真実性を証明することではなく、誰がいつ何を主張したかを改ざん不可能な形で記録し、改竄痕を可視化することへの設計転換である。

本記事で提示したNoireBoxの設計パターンは、この転換を具体化する多層防御構造である。ハッシュチェーンがイベント間の整合性を保証し、Ed25519署名が作成者を証明し、RFC 3161準拠のTSAアンカーが外部からの独立検証を可能にする。これらの層を組み合わせることで、内部担当者による日付偽装やイベントの挿入・削除を検知可能な状態に近づけることができる。

ただし、この仕組みが保証するのは「記録が作成以降改ざんされていないこと」と「作成日時」であり、記録内容の真偽までは保証しない。エージェントが悪意を持って正しい手順で偽の情報を出力した場合、ログは不変のまま内容だけが虚偽となる可能性がある。監査ログは「お守り」ではなく「道具」であり、改竄痕を検知するための手段として位置づける必要がある。真に信頼できるAIシステムを実現するには、この不変性保証の基盤の上に、コンテンツ検証層と人間の判断を伴う運用プロセスを重ねていくことが望ましい。

関連記事

参考

本記事は海外の技術トレンド「The Witness Was the Suspect: Why AI Audit Logs Can't Be Trusted」(DEV)で話題のテーマをもとに、両儀システムソリューションズが独自に解説したものです。