パスワードをスクリプトや 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 をご覧ください。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 をご覧ください。

注意と制限

よくある質問

AI エージェントにパスワードを渡しても大丈夫ですか。
チャットに貼った値は会話の一部としてモデルの提供元へ送られ、履歴にも残ります。値をモデルに見せずに、環境変数としてコマンドにだけ渡す方法を使ってください。
コマンドの引数にパスワードを書くと何が問題ですか。
実行中はプロセスの一覧からほかの利用者に見えることがあり、シェルの履歴にも残ります。環境変数、標準入力、入力の画面から渡してください。
Nodd の --secret で入れた値はサーバーで読めますか。
読めません。値はこの実行だけの鍵で暗号化して届きます。ただし公開鍵はサーバーを通るので、サーバーそのものが乗っ取られた場合の保護にはなりません。
MCP から秘密の値を求められますか。
できません。MCP には --secret にあたる機能がありません。エージェントには nodd ask --secret --env を CLI のコマンドとして実行させてください。
どのバージョンのアプリが必要ですか。
Nodd 1.1 以降のアプリが必要です。1.0 のアプリでは却下でしか答えられません。

Nodd は、スクリプトや CI、AI エージェントからの確認を iPhone に届け、Face ID での承認を送った側のプログラムへ返すアプリです。無料プランがあります。

関連する記事