1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AI agent の確認ダイアログは、OK ボタンではなく境界表示として作る

1
Posted at

最近の coding agent の確認ダイアログ、正直ちょっと信用しすぎていたなと思いました。

Claude Code、Cursor、Codex、Windsurf みたいな tool に作業を任せると、最後に diff を見て Accept する。コマンド実行なら「実行しますか」と聞かれる。体感としては、人間が最後の gate になっているように見える。

でも、その gate が何を見せているのか。

ここがずれていると、OK ボタンは安全装置ではなくなります。見えている path と、実際に書き込まれる path が違う。Accept / Reject の前に disk へ書かれている。UI は workspace 内のファイルに見せているのに、backend は symlink の解決先へ書いている。

これを「AI coding tool の脆弱性ニュース」として流すと、たぶん少し遠い話になります。実務ではもっと手元の問題で、approval UI と repo 運用の設計です。

GhostApproval の怖さは symlink そのものではない

GhostApproval として報じられた問題では、Unix の symlink を使って AI coding assistant の workspace sandbox や approval flow をすり抜ける例が紹介されています。対象として Amazon Q Developer、Claude Code、Cursor、Windsurf、Google Antigravity などの名前が挙がっていました。

symlink 自体は昔からあります。

怖いのは、agent runtime と UI の認識が割れることです。

たとえばこういう状態です。

UI に見えている path:
  ./tmp/generated/settings.json

実際に書き込まれる resolved path:
  /Users/me/.config/tool/settings.json

人間は ./tmp/generated/settings.json なら大丈夫そうだと判断する。でも実際には外側の設定ファイルが触られる。

この時、人間が Accept を押したことにどれだけ意味があるのか。判断材料が間違っているなら、承認は承認になっていません。

さらに厄介なのは、ツールによっては Accept / Reject の前に disk write が起きていたと報じられている点です。そうなると確認ダイアログは authorization gate ではなく、あとから戻すための undo UI に近い。

ここを混ぜると事故ります。

authorization gate:
  書き込む前に、人間が境界を見て許可する

undo UI:
  すでに書き込まれた後で、人間が戻すか決める

同じ Accept / Reject に見えても、実装の意味は全然違います。

approval で見たいのは diff summary ではなく境界

agent の確認 UI は、差分の要約だけ見せればよいわけではありません。

自分なら最低限これを見たいです。

## Agent approval checklist

- display path と resolved path が一致しているか
- workspace 外への read / write がないか
- symlink / hardlink / generated file を触っていないか
- ignored file や secret に近い file を触っていないか
- command execution と file write が同じ approval に混ざっていないか
- Accept 前に disk へ書かれていないか
- rollback できる差分単位になっているか

「この diff は良さそうですか」だけでは足りません。

diff が良さそうでも、触っている境界が怪しいことはあります。逆に、差分は少し大きくても、触っている範囲が明確なら review できることもある。

coding agent はもう autocomplete ではありません。ファイルを書き、コマンドを実行し、場合によっては複数 task を並行して進めます。Codex の利用分析でも、複数の concurrent agent を扱う使い方や skills 利用が増えているという話が出ています。

なので、人間が見るべきものも変わります。

「よさそうな patch か」だけではなく、「この agent はどの境界の中で動いたか」を見る必要があります。

repo 側で先に境界を決める

ツール側の approval UI が改善されるのは当然として、repo 側でもできることはあります。

自分なら、agent に渡す前に触ってよい場所を雑にでも書きます。

## Agent boundary notes

- allowed paths:
  - app/components/**
  - app/pages/resize-image-for-instagram.vue
  - tests/components/**
- blocked paths:
  - .env*
  - .ssh/**
  - package manager config
  - deployment config
  - files outside this repository
- human checked:
  - resolved paths
  - generated assets
  - command list

これを毎回きれいに書く必要はありません。task note でも PR template でも AGENTS.md でもいい。

先に決めたいのは、agent が「何をしてよいか」だけではありません。「どこから先は人間が見るか」です。

特に危ないのはこのあたりです。

- .env, SSH key, token, credential
- package manager config
- install script
- deploy config
- editor / IDE settings
- generated output
- ignored file
- workspace 外への symlink

frontend の日常作業でも普通に踏みます。

LP の文言修正を頼んだだけなのに routing config に触る。CSS の調整を頼んだだけなのに画像 asset を再生成する。OGP や SNS preview の修正で、元画像、生成物、page component、metadata config が同じ approval に混ざる。

こういう時は、agent の diff が正しいか以前に、作業単位が大きすぎます。

file write と command execution を分ける

自分が最近気にしているのは、file write と command execution を同じ承認に混ぜないことです。

たとえば agent がこう言ってきたとします。

I will update the component, install a missing package, and run tests.

便利そうです。

でも review するなら分けたい。

1. どの file を読むか
2. どの file を書くか
3. どの command を実行するか
4. command が install / migration / deploy に触るか
5. 実行後にどの generated file が変わるか

pnpm testpnpm install は同じ「command 実行」ではありません。

pnpm lint --fix と DB migration も全然違います。

agent が package を追加したいと言った時は、依存の出どころも見たいです。HalluSquatting のように、agent がもっともらしい repo や package 名を出し、攻撃者がその名前を取るタイプの話もあります。検索できたから安全、では弱い。canonical source、lockfile、install script、maintainer、download ではなく、少なくとも「なぜこれを入れるのか」を人間が説明できる状態にしたい。

UI / 画像 / generated artifact は境界が曖昧になりやすい

frontend で agent を使うと、UI 変更と artifact 変更が混ざりがちです。

たとえば AI で作った landing page の hero を直す。agent は component を編集し、画像を差し替え、metadata を変え、preview 用の asset まで触るかもしれない。

この時、自分なら確認を 2 つに分けます。

- repo に書き込む変更
- 人間が別 tool で確認する出力

画像サイズや SNS preview なら、agent に全部任せるより、人間が出力サイズを見た方が早い場面があります。Instagram 用の 1080 x 1080 / 1080 x 1350 / 1080 x 1920 みたいな確認では、ブラウザ内で画像を処理する Resize Image for Instagram のような tool を使い、repo の file write とは別の確認ステップにしておく。ここを混ぜない方が、あとで何を承認したのか追いやすいです。

同じことは UI generation の参考資料にも言えます。

Generative UI や agent-rendered UI のアイデアを探す時は、参考にする resource と、自分の repo に書き込む component を分ける。たとえば 生成AI UIデザインのリソース集 のような curated resource を眺めるのは input です。そこから agent が自分の codebase に何を書くかは、別の approval boundary です。

資料を見ることと、repo を変更することを同じ承認にしない。

地味ですが、ここを分けるだけで見通しがよくなります。

approval prompt に出してほしい情報

agent tool を作る側なら、approval prompt はこういう表示にしたいです。

Action:
  write files

Workspace:
  /Users/me/project

Files:
  app/components/Hero.vue
    display path: app/components/Hero.vue
    resolved path: /Users/me/project/app/components/Hero.vue
    status: inside workspace

  tmp/theme.json
    display path: tmp/theme.json
    resolved path: /Users/me/.config/theme.json
    status: outside workspace via symlink

Commands:
  none

Disk write timing:
  not written yet

Rollback:
  patch can be reverted as one diff

このくらい出ていれば、人間は少なくとも疑う場所を選べます。

逆に、The agent wants to modify 2 files. Accept? だと怖い。2 files が workspace 内なのか、symlink 先なのか、generated file なのか、ignored file なのかが分からない。

approval UI は安心感を出すための modal ではなく、境界を表示するための UI であるべきです。

チーム運用では 3 行だけ残す

毎回長い security checklist を書くのは続きません。

PR にはこのくらいでいいと思っています。

## Agent boundary

- allowed:
- suspicious / blocked:
- human checked:

例です。

## Agent boundary

- allowed:
  - `app/components/ProfileForm.vue`
  - `tests/profile-form.spec.ts`
- suspicious / blocked:
  - package install は未実行
  - `.env` と deploy config は読ませていない
- human checked:
  - resolved path が workspace 内だけであること
  - `pnpm test tests/profile-form.spec.ts`
  - Chrome で submit error の表示

これがあると reviewer は楽です。

「AI を使いました」だけでは情報が足りません。どこまで agent に任せたのか。どこで止めたのか。人間が何を見たのか。そこが分かると review できます。

agent は速いです。だからこそ、境界の記録がないと速く不安になります。

まとめ

agent の安全性は、最後に人間が OK を押すことでは作れません。

UI と workflow が、人間に判断できるだけの情報を出しているか。見るべきなのはそこです。

これから coding agent は、local terminal だけでなく remote task、mobile approval、overnight job に広がっていきます。画面の前に張り付いている時代より、あとから「何が許可されたのか」を追えることが重要になります。

Accept ボタンの前に、境界表示を設計する。

自分の repo で始めるなら、まずは次の PR に 3 行だけ足します。

## Agent boundary

- allowed:
- suspicious / blocked:
- human checked:

これだけでも、「agent が何をしたか」ではなく「人間が何を承認したか」に会話を戻せます。

Source notes

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?