.env を AI に安心して触らせる — 1Password CLI ラッパー「opx」とプロセススコープ認証の設計

@suin 氏のポストが、AI エージェント時代の .env 管理問題に対する実践的な解決策として、自作の 1Password CLI ラッパー「opx」を公開しています。

.envをAIに安心して触らせたくて、こんなの作った AIエージェントなしではもう開発が成り立たないほど必須になってきています。権限設定がいろいろできるにせよ、本質的にAIエージェントにはプロジェクトの全ファイルを触りうる力を与えているわけで、気になるのがシークレットなどの機密情報です。

Claude Code や Cursor などの AI コーディングエージェントは、開発者と同じ権限でファイルシステムにアクセスします。.env にアクセストークンや AWS キーを平文で書いていれば、エージェントはそれを読めてしまいます。この構造的な問題に対し、「.env に機密情報を一切書かない」というアプローチで解決するのが opx です。

問題の構造 — AI エージェントが .env を読める

なぜ危険なのか

AI コーディングエージェントは通常のプロセスとして動作し、シェル環境を継承します。

開発者のシェル
  └── AI エージェント(Claude Code, Cursor 等)
        ├── ファイルシステムへのフルアクセス
        ├── .env ファイルの読み取り
        ├── 環境変数の参照
        └── Bash コマンドの実行

.zshrcAWS_SECRET_ACCESS_KEY を書いていれば、エージェントもそれを持っています。プロンプトインジェクション攻撃を受けた場合、エージェントが意図せず機密情報を外部に送信するリスクがあります。

実際に報告されている脆弱性

2025年末に公開された「IDEsaster」と呼ばれる調査では、Cursor、Windsurf、GitHub Copilot、Cline など30以上の AI IDE に脆弱性が発見されています。OpenAI Codex CLI では .env ファイルを経由した任意コマンド実行の脆弱性(CVE-2025-61260)も報告されました。

脅威は理論上のものではなく、実際に存在する攻撃ベクトルです。

1Password CLI の仕組み — op:// 参照で平文を排除

従来の .env

1
2
3
4
# 危険: 平文のシークレットがファイルに存在
AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
STRIPE_SECRET_KEY=sk_live_xxxxxxxxxxxxx

1Password CLI を使った .env

1
2
3
4
5
# 安全: op:// 参照のみ。実際の値は 1Password Vault に保存
AWS_ACCESS_KEY_ID=op://Development/AWS/access-key-id
AWS_SECRET_ACCESS_KEY=op://Development/AWS/secret-access-key
STRIPE_SECRET_KEY=op://Development/Stripe/secret-key
PORT=3000

op:// は 1Password Vault 内のアイテムへの参照 URI です。実際のシークレットはファイルに存在せず、op run コマンドが実行時に動的に解決します。

1
2
# 実行時に 1Password が op:// を実際の値に置換
op run --env-file=.env -- npm run dev

このとき、Touch ID による認証が挟まります。シークレットは子プロセスの環境変数としてのみ注入され、プロセス終了時に消えます。

プロセススコープ認証の仕組み

1Password Vault(暗号化ストレージ)
  │
  ├── Touch ID 認証
  │
  └── op run コマンド
        │
        ├── .env の op:// 参照を解決
        ├── 子プロセスの環境変数として注入
        └── プロセス終了で自動削除
              │
              └── npm run dev(シークレットはこのプロセス内でのみ有効)

重要なのは、シークレットがシェル環境に残らないことです。export で設定した環境変数は他のプロセスからも参照できますが、op run で注入された値は指定した子プロセスだけが持ちます。

opx が解決する UX の問題

1Password CLI の仕組みは優れていますが、日常的に使うには不便な点がありました。

従来の op run の課題

1
2
3
4
5
6
# 長い。毎回打つのは面倒
op run --env-file=.env -- npm run dev

# サブディレクトリにいると相対パスが変わる
cd packages/api
op run --env-file=../../.env -- npm run dev

opx の解決策

1
2
# これだけ。.env の自動検索、パス解決も自動
opx npm run dev

opx は以下の問題を解決します。

課題op runopx
コマンドの長さop run --env-file=.env -- が必要opx だけ
.env のパス指定相対パスを毎回計算プロジェクトルートから自動検索
サブディレクトリ対応--env-file=../../.env自動で近くの .env を発見

インストール方法

1
2
3
4
5
6
7
8
# Bun
bun add -g @suin/opx

# mise
mise use -g github:suin/opx

# curl
curl -fsSL https://raw.githubusercontent.com/suin/install/main/install.sh | bash -s -- opx

.env をバージョン管理に含められる

opx/1Password CLI 方式の副次的な利点として、.env ファイルを Git にコミットできるようになります。

1
2
3
4
5
6
7
# .gitignore から .env を除外可能
# ファイルには op:// 参照しか含まれないため安全

# .env の中身
DATABASE_URL=op://Development/Database/url
STRIPE_SECRET_KEY=op://Development/Stripe/secret-key
PORT=3000

従来はチームメンバーに .env.example を渡して「各自で値を埋めてね」という運用が一般的でした。opx 方式では .env そのものを共有でき、1Password の Vault 共有で値もチーム内で同期できます。

1Password Environments — さらに進んだ公式機能

2025年10月、1Password は「1Password Environments」をパブリックベータとしてリリースしました。これは .env ファイルを仮想的にマウントする機能です。

比較opx / op run1Password Environments
仕組みコマンド実行時に動的注入ファイルシステムレベルで仮想マウント
.env ファイルop:// 参照を書いたファイルが必要ディスク上に .env ファイルが不要
対応環境全プラットフォームMac / Linux(Windows 開発中)
ステータス安定版パブリックベータ

Environments はより根本的な解決策ですが、まだベータ段階です。opx は現時点で安定して使える実用的なアプローチです。

AI エージェント時代の .env 防御 3層モデル

dreamiurg.net の記事が提案する3層防御モデルは、opx の位置づけを理解するのに有用です。

対策効果
第1層: サンドボックスDocker / DevContainer / Bubblewrapファイルシステムとネットワークを制限
第2層: 最小権限の認証情報opx / op run / プロセススコープ注入シークレットの露出範囲を限定
第3層: エージェント権限制御deny ルール / .env アクセス禁止エージェントの行動を制限

opx は第2層に位置します。シェル環境に認証情報を置かず、必要なプロセスにだけ注入することで、エージェントが受動的にシークレットを漏洩するリスクを排除します。

ただし、エージェントがファイルシステムへの書き込み権限を持つ場合、.mcp.json の改変や注入されたシークレットの傍受は理論的に可能です。プロセススコープ認証は受動的漏洩の防止であり、能動的攻撃に対しては第1層のサンドボックスが必要です。

Claude Code での実践設定

Claude Code で opx を活用する場合の設定例です。

CLAUDE.md に使用方法を記載

1
2
3
## 開発サーバー起動
- `opx npm run dev` で起動(.env のシークレットは 1Password 経由で注入)
- .env ファイルを直接編集しないこと(op:// 参照のみ含む)

settings.json で .env への直接アクセスを制限

1
2
3
4
5
6
7
8
{
  "permissions": {
    "deny": [
      "Read(.env*)",
      "Edit(.env*)"
    ]
  }
}

フック(hooks)でシークレットの平文書き込みを検知

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "command": "grep -l 'sk_live\\|AKIA\\|ghp_' \"$TOOL_INPUT_FILE_PATH\" 2>/dev/null && echo 'WARNING: Possible secret in file' && exit 1 || true"
      }
    ]
  }
}

まとめ

  • AI エージェントは .env を読める: Claude Code や Cursor は開発者と同じ権限でファイルにアクセスする。平文のシークレットは構造的にリスク
  • opx は op run の UX 問題を解決: コマンドの長さ、.env パスの手動指定、サブディレクトリ対応を自動化
  • op:// 参照で平文を排除: .env にシークレットの実体を書かず、1Password Vault への参照だけを記載。Git コミットも可能
  • プロセススコープ認証が鍵: シークレットは子プロセスの環境変数としてのみ注入され、プロセス終了で消える。シェル環境に残らない
  • 3層防御の第2層: サンドボックス(第1層)、プロセススコープ認証(第2層)、エージェント権限制御(第3層)の組み合わせが理想
  • 1Password Environments は次の一手: .env ファイル自体を仮想マウントする公式機能がベータ提供中。opx は現時点で安定した実用解
  • 受動的漏洩を防ぐ: opx は「エージェントがうっかり読む」リスクを排除する。能動的攻撃にはサンドボックスが必要

参考