パスワードをスクリプトや AI エージェントに安全に渡す方法
公開日:2026-11-08
パスワードはチャットやコマンドの引数に書かず、read -s の入力、1Password の op run などのパスワード管理の CLI、クラウドのシークレット管理、OS のキーチェーンから、実行のときに環境変数や標準入力で渡すのが基本です。その場で人が入力する必要があるなら、Nodd の nodd ask --secret --env で iPhone の伏せた入力欄から受け取れます。値はこの実行だけの鍵で暗号化して届き、--env を使えば AI エージェントのモデルには渡りません。
秘密の値が漏れる経路
パスワードや API トークンは、使う瞬間より前後の扱いで漏れることが多いです。よくある経路は次のとおりです。
チャットや AI エージェントに貼る
チャットに貼った値は会話の一部になり、モデルの提供元へ送られます。ツールによっては手元にも会話の履歴が残ります。たとえば Claude Code は、セッションの履歴を ~/.claude 以下に保存します。エージェントが値をコマンドに埋め込めば、そのコマンドもログや画面に残ります。
コマンドの引数に書く
mysql -pPASSWORD のように引数に書くと、実行中は ps などでほかの利用者からも見えることがあります。Linux では /proc/<pid>/cmdline が既定でほかの利用者から読めます(hidepid のマウントオプションで隠せます)。シェルの履歴ファイルにも残ります。bash の HISTCONTROL=ignorespace は、先頭に空白のあるコマンドを履歴に残さない設定ですが、実行中の引数は隠せません。
平文の .env をコミットする
.env を .gitignore に入れ忘れると、値がリポジトリの履歴に残ります。GitHub の push protection は秘密の値を含む push を止めます。利用者ごとの保護は GitHub.com で既定で有効で、公開リポジトリへの push が対象です。リポジトリごとの保護は既定では無効なので、管理者が有効にする必要があります。
よく使われる安全な方法
read -s でその場で入力する
bash の read -s は、端末からの入力を画面に表示しません。手元で 1 回だけ実行するスクリプトなら、これで十分です。
read -rsp "DB password: " PGPASSWORD
echo
export PGPASSWORD
psql -h db.example.com app
端末の前に人がいることが前提です。CI や、AI エージェントが動かすコマンドでは使えません。
パスワード管理の CLI
1Password CLI では、op://保管庫/アイテム/フィールド の参照を書いたファイルを op run --env-file に渡すと、実行するコマンドの環境変数にだけ本当の値が入ります。コマンドが値を出力すると、既定で伏せ字に置き換えます。参照だけのファイルなので、Git に入れられます。1 つの値だけ読むなら op read です。
# .env (commit-safe: it holds only references)
PGPASSWORD="op://Production/app-db/password"
op run --env-file=.env -- psql -h db.example.com app
クラウドのシークレット管理
AWS Secrets Manager のようなサービスは、値をソースコードに書かず、実行のときに API で取り出す仕組みです。IAM での権限の管理、自動のローテーション、CloudTrail での記録ができます。サーバーや CI で動く処理には、これが向いています。
OS のキーチェーン
macOS では security find-generic-password の -w で、キーチェーンのパスワードだけを取り出せます。
PGPASSWORD="$(security find-generic-password -s app-db -a deploy -w)" psql -h db.example.com app
AI エージェントを使う場合は、秘密のファイルを読ませない設定も合わせます。Claude Code では、設定の permissions.deny に Read(./.env) のような規則を書けます。
方法の比べ方
| 方法 | 向いている場面 |
|---|---|
read -s | 端末の前で自分が実行するスクリプト |
パスワード管理の CLI(op run など) | 値がすでに保管庫にあり、手元や CI で繰り返し使うとき |
| クラウドのシークレット管理 | サーバーやバッチで、権限の管理やローテーションが要るとき |
| OS のキーチェーン | 1 台の Mac で自分だけが使う値 |
Nodd の --secret | その場で人が入力する必要があり、端末の前にいないとき。AI エージェントにコマンドを任せていて、値をモデルに見せたくないとき |
値が保管庫に入っていて、自動で取り出せるなら、パスワード管理の CLI やシークレット管理のほうが手間は少なくなります。Nodd は、値が人の頭の中や別の場所にあって、毎回の実行に人の判断を挟みたい場面に使います。
iPhone から一度だけ入力して渡す
nodd ask --secret は、iPhone に承認の依頼を送り、伏せた入力欄でパスワードなどを求めます。答える人は値を入れて「Face IDで送信」を押します。回答には Nodd 1.1 以降のアプリが必要です。
AI エージェントには --env を使う
nodd ask "本番 DB のパスワード" --secret --env PGPASSWORD -- psql -h db.example.com app
--env を付けると、承認されたときだけ -- の後のコマンドを実行し、値はそのコマンドの環境変数 PGPASSWORD にだけ入ります。標準出力には値を出しません。エージェントにはこの形でコマンドを書かせれば、値はモデルに渡りません。終了コードはそのコマンドのものです。却下や期限切れでは値を返さず、コマンドも実行しません。
パイプで渡す
nodd ask "API トークン" --secret | ./import-token.sh
--env なしでは、標準出力へ値だけを出します。端末へそのまま表示はしないので、パイプするか --env を使います。
値の扱い
- 値は、この実行のあいだだけある鍵で暗号化して届きます。サーバーでは読めません
- サーバーに残るのは暗号文だけです。CLI は受け取って開けたら消し、消せなくても 10 分で消えます
- 値は応答の
response、イベント、callback には入りません - 端末にも残さず、アプリの履歴には「入力した値」とだけ表示します
答える側は、画面に出る送信キーの名前とチャンネルを確かめてください。心当たりがなければ却下します。セットアップはクイックスタート、指定の一覧は CLI をご覧ください。Claude Code と組み合わせる例はこちらの記事にあります。
API で使う
CLI を使わずに自分のプログラムから求めるときは、approval の secret.public_key に、Base64 の 32 バイトの X25519 公開鍵を入れます。端末はこの鍵で値を暗号化します。承認された後に GET /v1/messages/{id}/secret で {"sealed": "…"} を受け取り、読んだら DELETE で消します。
curl https://api.nodd.blipdrop.net/v1/messages \
-H "Authorization: Bearer $NODD_KEY" \
-H "Content-Type: application/json" \
-d '{"kind":"approval","title":"本番 DB のパスワード","secret":{"public_key":"<Base64 の X25519 公開鍵>"}}'
# 承認された後に暗号文を受け取り、開けたら消す
curl https://api.nodd.blipdrop.net/v1/messages/msg_.../secret -H "Authorization: Bearer $NODD_KEY"
curl -X DELETE https://api.nodd.blipdrop.net/v1/messages/msg_.../secret -H "Authorization: Bearer $NODD_KEY"
暗号は HPKE(DHKEM X25519 / HKDF-SHA256 / ChaCha20-Poly1305)で、info は nod-secret-v1、追加データは通知の ID です。response.secret_digest は暗号文の Base64 文字列の SHA-256 で、署名の対象です。詳しくは API をご覧ください。
注意と制限
- 回答には Nodd 1.1 以降のアプリが必要です。1.0 のアプリは、秘密の値の依頼に却下でしか答えられません
--secretは MCP にはありません。エージェントには CLI のコマンドとして実行させますsecretはinput、dedupe_key、confirm: false、2 人以上の承認とは併用できません。CLI では--option、--input、--approvals、--no-wait、--jsonと一緒に使えません- 公開鍵はサーバーを通るので、サーバーそのものが乗っ取られた場合の保護にはなりません
--envで渡した値も、実行したコマンドが出力すればエージェントに見えます。値を表示しないコマンドに渡してください--inputの文字の入力は暗号化の対象外です。秘密の値には使わないでください
よくある質問
- AI エージェントにパスワードを渡しても大丈夫ですか。
- チャットに貼った値は会話の一部としてモデルの提供元へ送られ、履歴にも残ります。値をモデルに見せずに、環境変数としてコマンドにだけ渡す方法を使ってください。
- コマンドの引数にパスワードを書くと何が問題ですか。
- 実行中はプロセスの一覧からほかの利用者に見えることがあり、シェルの履歴にも残ります。環境変数、標準入力、入力の画面から渡してください。
- Nodd の --secret で入れた値はサーバーで読めますか。
- 読めません。値はこの実行だけの鍵で暗号化して届きます。ただし公開鍵はサーバーを通るので、サーバーそのものが乗っ取られた場合の保護にはなりません。
- MCP から秘密の値を求められますか。
- できません。MCP には --secret にあたる機能がありません。エージェントには nodd ask --secret --env を CLI のコマンドとして実行させてください。
- どのバージョンのアプリが必要ですか。
- Nodd 1.1 以降のアプリが必要です。1.0 のアプリでは却下でしか答えられません。
Nodd は、スクリプトや CI、AI エージェントからの確認を iPhone に届け、Face ID での承認を送った側のプログラムへ返すアプリです。無料プランがあります。