要約

  • RFC 9987の署名要求は公開鍵、データ、フラグを送り、署名または失敗を受け取る。発信元プロセス、人、接続先ホスト、遠隔アカウント、コマンド、目的を示す必須欄はない。
  • エージェントプロトコル自体にはクライアント認証も通信路保護もない。通常はローカルのエンドポイントへの到達可能性が利用権となり、エージェント転送は秘密鍵を動かさずにその利用能力を別ホストへ渡す。
  • 確認、有効期間、ロック、エージェントの結果、サーバー認証、アプリケーション認可は独立した判断である。Daniel Kadeは秘密を保存しない六段階の署名意図受領記録を提案する。

緑色の結果が答えていないこと

監査画面に三つの成功が並ぶ。エージェントは署名を返した。署名検証は通った。秘密鍵はハードウェアから出ていない。そこで「本人が承認した」と結論すると、記録にない意味を加えることになる。どのプロセスがエンドポイントへ入ったのか。ローカル要求か、転送された遠隔要求か。その時点の制約は何か。確認画面は目的地と影響を説明したか。遠隔サーバーは最終的に何を許したか。成功欄だけでは答えられない。

2026年5月にIETF Proposed Standardとして公開されたRFC 9987は、クライアントとSSHエージェントの間の要求・応答を定める。エージェントは秘密鍵を保持し、または鍵操作を委任できる。クライアントは識別子の追加、削除、一覧取得、署名、ロック、拡張を要求する。長く使われてきた境界を共通化する仕様だが、署名対象の業務的な意味まで理解する主体ではない。

SSH_AGENTC_SIGN_REQUESTに含まれるのは公開鍵blob、データ列、flagsである。成功応答SSH_AGENT_SIGN_RESPONSEは署名を返す。実行ファイル、自然人、対象ホスト、ユーザー名、コマンド、承認票、認可規則を必ず伝える欄はない。データがSSH認証要求を表す場合でも、汎用のエージェントメッセージは用途を限定しておらず、受信側が後でどの権限を与えるかも知らない。

これは標準の欠陥ではない。狭いインターフェースは相互運用と防御を容易にする。問題は運用側が「鍵がデータへ署名した」を「利用者が結果に同意した」へ読み替える時に生じる。Why BTW Media Existsが重視するように、観測と主張を分ける必要がある。観測できたのは鍵操作であり、同意と認可には別の証拠が要る。

保管の強さと呼出し権限は別物である

RFC 9987は、エージェントプロトコル自身がクライアントを認証せず、通信の安全性も提供しないと明記する。一般的な実装はローカルsocketやnamed pipeを使い、OSが所有者とアクセス権を制限する。エンドポイントに届けば、見えている鍵で秘密鍵操作を要求できることが多い。鍵の所在だけでなく、誰がこの入口に届くかが制御面になる。

攻撃者は鍵を抽出できなくても、到達可能で無制約のエージェントを署名oracleとして使える。RFCは、無制約な代理がサイドチャネル観測に都合のよいoracleにもなり得ると警告する。「非エクスポート」は複製を防いだ証拠であって、すべての呼出しが正当だった証拠ではない。

ハードウェアトークンでは、エージェント上の状態と装置上の状態を混同しやすい。トークンの識別子をエージェントへ追加しても、実際の鍵操作は装置に委任される。エージェントから削除しても、トークンの鍵を消すべきではない。インシデント記録の「鍵を削除した」は、どの層から、どのload epochを終えたのかを示さなければならない。

The Policy Mirrorの考え方を適用すると、方針は実際の意思決定点に合わせる必要がある。OSが入口を制御し、エージェントが制約を適用し、トークンが鍵素材と在席確認を担うことがある。SSHサーバーは要求されたアカウントに鍵を認めるかを決め、さらにサービスが行為を認可する。どの判断も署名一件に吸収されない。

制約には有効だった時刻がある

鍵の追加時には、有効期間や各秘密鍵操作の前の確認を制約として付けられる。名前付き拡張で別の制約を表すこともできる。要求された制約を理解できないエージェントは、制約なしで黙って追加せず、処理を失敗させなければならない。期待した防御が知らないうちに消えるのを防ぐ原則である。

しかし制約は変化する。同じ鍵を再び追加した場合、新しい要求で以前の制約を置き換えるべきであり、そうしない実装は追加を拒否できる。したがって鍵fingerprintだけでは、その瞬間の権限を表さない。loadまたはreplacement epochを設け、署名を有効期間、確認、拡張、可視範囲、ロック状態に結び付ける必要がある。事後の一覧は当時の状態とは限らない。

確認も自動的に知情同意にはならない。ボタン押下は画面が肯定を受けた事実にすぎない。人が接続先、アカウント、プロトコル、結果を安全で正確な形で見た時に初めて意味を持つ。生データ表示は秘密を漏らし得る一方、「鍵を使いますか」だけでは説明にならない。わかりやすい要約の版と、実際の署名データのハッシュを結ぶ設計が必要である。

ロック解除も同様だ。ロック中のエージェントは、正しいpassphraseで解除されるまで少なくとも秘密鍵署名を停止する。解除は能力を利用可能にしただけで、次の依頼者や目的地を承認していない。これを包括的な同意にすると、一時的な状態変更が将来の全要求へ広がってしまう。

転送は秘密ではなく権限を運ぶ

エージェント転送を使えば、遠隔ホストは秘密鍵を受け取らずにローカル鍵を利用できる。この保護は重要だが、同時に委任でもある。RFC 9987は転送をtransitive trustと位置付け、既定で有効にしないこと、十分に信頼できないホストへ転送しないことを勧める。遠隔ホスト上の攻撃者は、鍵を盗まずにローカルエージェントへ操作を頼める。

追跡には構造上の限界もある。agent-connectには接続要求の元になったsession channelを区別する識別子がない。一つのSSH接続に複数セッションがあり、同時に転送要求が動けば、ローカル側から「このtransport経由」と分かっても、特定のshell、プロセス、人まで確定できないことがある。

Running Code Primaryの原則では、宣言より実際に動いた境界を証拠にする。socketの所有と権限、得られるpeer情報、転送選択、制約epoch、要求時刻、検証側の結果を結合する。「転送禁止」という設定だけでは、個別署名が通った経路を証明できない。

認証成功を決めるのはサーバーである

RFC 4252の公開鍵利用者認証では、サーバーが鍵を対象ユーザーのauthenticatorとして受け入れるかを判断し、署名を検証する。署名対象にはsession identifierと、ユーザー名、サービス、方式、アルゴリズム、公開鍵などが入る。追加要素を要求する場合もある。完全な認証成功はサーバーのSSH_MSG_USERAUTH_SUCCESSであり、先行するエージェント応答ではない。

RFC 4253は保護されたtransportとsession identifierを、RFC 4254は認証後のchannelとserviceを、RFC 4251は全体構造を定める。この分離によって、鍵利用、アカウント認証、コマンド認可は別々の結果として残る。

アルゴリズム登録も権限を示さない。RFC 8332はRSA SHA-2、RFC 8709はEd25519とEd448、RFC 8308は拡張交渉を扱う。IANA SSH Parametersは識別子を共有する場所であり、導入、公開、承認、認可の証拠ではない。

六段階の署名意図受領記録

第一段階は依頼者の受付で、localかforwardedか、利用可能な最小peer参照、policy epoch、不透明な要求IDを記録する。第二段階は鍵状態で、公開fingerprint、可視範囲、load epoch、有効期間、確認と拡張制約、token委任、ロックを残す。

第三段階は操作で、正確なデータの長さと衝突耐性hash、algorithm、flagsだけを広域記録し、生の機密データは複製しない。第四段階は確認の要否、表示した安全な要約、信頼できる操作面、approve・deny・unavailableの結果を残す。第五段階はエージェントの成否と拒否分類。第六段階は依存システムのprotocol、destination、session、account、検証、追加要素、後段の認可と訂正経路である。

これはDaniel Kadeによるガバナンス提案であり、RFC 9987の必須項目ではない。エージェントに業務判断を背負わせず、一つの技術的成功が権限全体の証明に化けることを防ぐための枠組みである。

参照資料