0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

set -a; source .env すると子プロセスにも API キーが渡る:source だけでは渡らない(実機確認)

0
Posted at

結論

  • .env をそのまま source しただけでは、シェル変数には入っても export されないので、子プロセス(別の bash や Python)からは見えません(2026-11-07、bash 5.2.37・ダミー値で実機確認)。
  • よく紹介される set -a; source .env; set +a を使うと、代入した変数がすべて export 扱いになり、子プロセスにも API キーや DB パスワードが渡ります。
  • .env の各行に最初から export を書いてある場合も、set -a なしで同じように子へ渡ります。
  • AIエージェントに「.env を読んでコマンドを実行して」と頼むと、set -a 付きの source が使われることがあります(推測。今回はエージェント経由では試していません)。スクリプトに残っていないかは、下の1行で探せます。

この記事は「AIエージェントと秘密情報」の検証シリーズです。新しい検証は X(@supportapp3_lab)でもお知らせしています。

試してみる(set -a や source .env が残っていないか)

プロジェクトのフォルダで実行すると、set -a / set +a / allexport / source と .env が近い行のファイル名と行番号を出します。

grep -rnE --include='*.sh' --include='*.bash' --include='*.zsh' \
  'set -a|set \+a|allexport|source[[:space:]]+.*\.env|\.[[:space:]]+.*\.env' .

出てきたスクリプトが、そのあと別コマンドや Python を起動していれば、鍵が子プロセスの環境に入ります。

.env 系のファイル名だけ先に見たい場合は、読み取り専用の CLI もあります。

npx github:supportapp3-lab/ai-secret-check scan

リポジトリ: https://github.com/supportapp3-lab/ai-secret-check

公式の説明

bash の help set(bash 5.2.37)には次のように書かれています。

-a Mark variables which are modified or created for export.

オプション名では allexport と同じです。つまり set -a のあいだに作られた・書き換えられた変数は、すべて export 属性が付きます。set +a でそのマークは止まりますが、すでに付いた export 属性は外れません(実機で確認)。

実機で確かめたこと

値はすべてダミーです。箱に入っている本物のトークンが混ざらないよう、env -i で最小限の環境から起動して試しました。

.env(export なし):

API_KEY=sk-dummy-0000-not-real
DB_PASSWORD=dummy-db-pass-1111

.env_export(各行に export):

export API_KEY=sk-dummy-export-2222
export DB_PASSWORD=dummy-db-export-3333

1. source だけ(set -a なし)→ 子には渡らない

set +a
source ./.env
echo "shell: API_KEY=${API_KEY-<empty>}"
printenv | grep -E '^(API_KEY|DB_PASSWORD)=' || echo "(none)"
# 子プロセス
env | grep -E '^(API_KEY|DB_PASSWORD)=' || echo "(none in child)"
declare -p API_KEY
shell: API_KEY=sk-dummy-0000-not-real
(none)
(none in child)
declare -- API_KEY="sk-dummy-0000-not-real"

シェル変数としては入りますが、declare --(export なし)なので、printenv にも子の env にも出ません。

2. set -a; source; set +a → 子にも渡る

set -a
source ./.env
set +a
printenv | grep -E '^(API_KEY|DB_PASSWORD)='
env | grep -E '^(API_KEY|DB_PASSWORD)='
declare -p API_KEY
DB_PASSWORD=dummy-db-pass-1111
API_KEY=sk-dummy-0000-not-real
DB_PASSWORD=dummy-db-pass-1111
API_KEY=sk-dummy-0000-not-real
declare -x API_KEY="sk-dummy-0000-not-real"

declare -x になり、子プロセスの環境にも同じ値が入りました。

3. Python の子プロセスでも同じ

set -a; source ./.env; set +a
python3 -c 'import os; print(os.environ.get("API_KEY","<missing>"))'
sk-dummy-0000-not-real

一方、set -a なしで source したあとの Python では <missing> でした。

4. .env に最初から export がある場合

set +a
source ./.env_export
printenv | grep -E '^(API_KEY|DB_PASSWORD)='
DB_PASSWORD=dummy-db-export-3333
API_KEY=sk-dummy-export-2222

set -a なしでも、行頭の export で子に渡ります。

昨日の printenv 記事との違い

printenv / env の記事は、「すでに export された環境を一覧で出すと鍵が見える」話でした。今回は その手前で、なぜ export されるのか(set -a や行頭の export)を切り分けています。

  • source .env だけ … シェル変数(子には渡らない)
  • set -a; source .env; set +a または export KEY=... … 環境変数(子にも渡る)
  • そのあと printenv / env … 渡った値を一覧で出す

/proc/PID/environ の記事は「別プロセスから読める」話で、こちらは 自分が起動した子に渡してしまう話です。

AIエージェントとの関係(ここからは推測を含みます)

  • 「.env を読んでからテストを走らせて」と頼むと、エージェントが set -a; source .env; set +a や export $(cat .env) 系を使うことがあります(推測。今回はエージェント経由では未確認)。
  • その場合、エージェントが起動した子コマンド(curl・テストランナー・別言語のプロセス)にも同じ鍵が渡ります(推測)。
  • Codex の shell_environment_policy の記事は「親シェルがもともと持っている環境変数を渡す」話で、今回は source の瞬間に export してしまう話です。両方あると、子にも会話ログにも残りやすくなります(推測)。

対策

  1. 上の grep で、set -a / source .env が残っていないか見る。
  2. どうしても source するなら、必要な変数だけ export API_KEY のように明示する(全部まとめて set -a しない)。
  3. 一時的に set -a した場合は、使い終わったら set +a したうえで、渡したくない変数は unset する(すでに子へ渡った分は戻らない)。
  4. AIに .env 読み込みを頼むときは、「子プロセスには渡さず、このシェル内だけで使う」と条件を付ける。

ai-secret-check について

ai-secret-check scan は、AIが読めそうな場所にある .env 系のファイル名を探します(中身は表示しません)。set -a の有無までは見ないので、上の grep とセットで見てください。

npx github:supportapp3-lab/ai-secret-check scan

リポジトリ: https://github.com/supportapp3-lab/ai-secret-check (Node.js 20以上、MIT)

参考

※ 2026-11-07 に、Debian の使い捨てフォルダとダミー値で確かめました(bash 5.2.37)。env -i で隔離して実行しています。

更新情報やちょっとしたTipsは X(@supportapp3_lab)で発信しています。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?