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?

python-dotenv の load_dotenv() は親フォルダの .env まで読む:プロジェクトに .env が無くても値が入るのを実機で確認(Node --env-file との違い)

0
Posted at

結論

  • Python の python-dotenv の load_dotenv() は、引数なしだとスクリプトのあるフォルダから上の階層へ順に .env を探し、最初に見つかった1つを読みます。
  • そのため、プロジェクトに .env が無くても、親フォルダに置いた別の .env の値が os.environ に入りました(2026-11-04、python-dotenv 1.2.4・Python 3.13.5、ダミー値で実機確認)。
  • Node.js の node --env-file=.env は、指定したパスだけを読み、親フォルダは探しませんでした(Node.js v24.22.1)。
  • AIエージェントにプロジェクトのフォルダだけを渡しても、そこで動かした Python スクリプトが上の階層の .env を読むことがあります。親フォルダに .env が無いかは、下の1行で確かめられます。

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

試してみる(親フォルダの .env を探す)

プロジェクトのフォルダで実行すると、そこから / までの各階層にある .env のパスだけを出します(中身は表示しません)。

d=$PWD; while [ "$d" != / ]; do ls -1 "$d"/.env 2>/dev/null; d=$(dirname "$d"); done

2つ以上出たら、Python スクリプトの置き場所によっては上の .env が読まれることがあります。

公式ドキュメントの説明

python-dotenv の README には、load_dotenv() は既定で次のように動くと書かれています。

Look for a .env file in the same directory as the Python script (or higher up the directory tree).
Not override existing environment variables (override=False).

ソースの find_dotenv() の説明も「Search in increasingly higher folders for the given file」です。基準はカレントディレクトリではなくスクリプトのある場所です(対話モードなどでは usecwd の扱いが変わります)。

実機で確かめたこと

用意したフォルダ(値はすべてダミー)

demo/
├── .env                 # DUMMY_PARENT_KEY=parent-dummy-0000
└── project/
    ├── .env             # DUMMY_PROJ_KEY=proj-dummy-1111
    └── app/sub/run.py

run.py は次のとおりです。

import os
from dotenv import load_dotenv, find_dotenv
print("find_dotenv():", find_dotenv(usecwd=False))
print("load_dotenv():", load_dotenv())
print("DUMMY_PROJ_KEY =", os.getenv("DUMMY_PROJ_KEY"))
print("DUMMY_PARENT_KEY =", os.getenv("DUMMY_PARENT_KEY"))

1. project/.env がある場合

find_dotenv(): /tmp/demo/project/.env
load_dotenv(): True
DUMMY_PROJ_KEY = proj-dummy-1111
DUMMY_PARENT_KEY = None

2階層上の project/.env が見つかり、そこで探すのをやめました。さらに上の demo/.env は読まれていません。

2. project/.env を消した場合

find_dotenv(): /tmp/demo/.env
load_dotenv(): True
DUMMY_PROJ_KEY = None
DUMMY_PARENT_KEY = parent-dummy-0000

プロジェクトの外にある demo/.env の値が入りました。エラーも警告も出ません。

3. 別のフォルダから実行しても同じ

.env の無い /tmp に移動してから python /path/to/run.py で実行しても、1と同じく project/.env が読まれました。探す起点はスクリプトの場所です。

4. すでにある環境変数は上書きしない

$ DUMMY_PROJ_KEY=from-shell python run.py
DUMMY_PROJ_KEY = from-shell

README のとおり、既定の override=False では、シェル側の値が優先されました。

5. dotenv_path を相対パスで書くと、カレントディレクトリ基準になる

app/sub で load_dotenv(dotenv_path="./.env") を実行すると False が返り、どちらの値も入りませんでした。この場合は上の階層を探しません。

6. Node.js の --env-file は親を探さない

$ node --env-file-if-exists=.env -e 'console.log(process.env.DUMMY_PROJ_KEY, process.env.DUMMY_PARENT_KEY)'
.env not found. Continuing without it.
undefined undefined
$ node --env-file=.env -e ''
node: .env: not found

同じ app/sub で実行すると、--env-file は指定したパスだけを見て、見つからなければエラーになりました。Node.js の公式ドキュメントにも、環境とファイルの両方にある変数は環境の値が優先されると書かれています。

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

  • Claude Code の公式ドキュメント(Permissions)には、Read・Edit の deny ルールは組み込みのファイル操作や Bash の cat などには効くが、「Python や Node のスクリプトが自分でファイルを開く」ような間接的な読み取りには効かない、と書かれています。load_dotenv() が親フォルダの .env を開くのはこの形なので、deny 設定では止まらないと考えられます(推測。今回は Claude Code 経由では試していません)。公式はすべてのプロセスを止めたい場合にサンドボックスを案内しています。
  • 一方 Codex の permission profile の deny はサンドボックスで効くので、記事7では codex sandbox -- cat .env が Permission denied になりました。ただし deny の対象を :workspace_roots の下に書いた場合、その外にある親フォルダの .env は対象外になると考えられます(推測、未確認)。
  • 読み込まれた値はそのプロセスの環境変数になるので、ログやエラー出力に出せば画面に出ます(/proc/PID/environ の記事で確かめたとおり、環境変数は同じユーザーから読めます)。
  • 親フォルダに .env を置く使い方(複数プロジェクトで共有するなど)をしている場合、プロジェクトのフォルダだけを点検しても見落とします。

対策

  1. 上の1行で、親フォルダに .env が無いか確かめる。
  2. Python では、読む .env のパスを決めて書く。スクリプトの場所を基準にするなら次のようにします。
    from pathlib import Path
    from dotenv import load_dotenv
    load_dotenv(dotenv_path=Path(__file__).resolve().parent / ".env")
    
    指定したファイルが無ければ False が返るので、上の階層を読みにいきません。
  3. 共有用の .env をホームなど上の階層に置かない。

ai-secret-check で見られる範囲

筆者が作った読み取り専用の CLI ai-secret-check scan は、起動したフォルダより下の .env 系ファイル名を探します。今回の demo/project で実行すると、project/.env は検出しましたが、親の demo/.env は対象外でした。project/.env を消した状態では「読めそうなファイルは見つかりませんでした。」と出ます。親フォルダは、上の1行で別に確かめてください。

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

リポジトリ: https://github.com/supportapp3-lab/ai-secret-check (Node.js 20以上、MIT。値は表示しません)

参考

※ 2026-11-04 に、Debian の使い捨てフォルダとダミー値で確かめました(python-dotenv 1.2.4、Python 3.13.5、Node.js v24.22.1)。出力中の /tmp/demo は実際のパスを置き換えたものです。

更新情報やちょっとした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?