結論
-
.npmignoreを置くと、npm は.gitignoreを読まなくなります(npm公式)。.gitignoreに.envを書いてあっても、.npmignoreにtest/だけを書いた状態でnpm pack --dry-runを実行すると、.env・.env.local・鍵ファイルがパッケージに入りました(筆者の環境で確認)。 -
package.jsonのfilesにディレクトリを丸ごと書くと、その中の.env.productionや*.pemも入りました。ルートの.gitignoreはfilesで指定した中身を外しませんでした(筆者の環境で確認)。 - 公開前に
npm pack --dry-runで入るファイルの一覧を見るのが一番確実です。filesはsrcのように必要なものだけを書き、.npmignoreを使うなら.env*と鍵の形式も書きます。
この記事は「AIエージェントと秘密情報」の検証シリーズです。新しい検証は X(@supportapp3_lab)でもお知らせしています。
AIに作らせた CLI やライブラリを npm で公開するとき、.npmignore を「テスト用ファイルを外すため」に足すことがあります。そのとき .gitignore で守っていた .env まで外れてしまわないかを確かめました。AIエージェントが実際にこの書き方をするかどうかは確かめていません。
検証環境と範囲
- Debian 13 / Node.js 20.19.2 / npm 11.21.0
-
npm pack --dry-runとnpm publish --dry-runだけを使いました。レジストリへの公開はしていません(publish --dry-runもログインなしで実行し、送信していません)。 -
.envと鍵ファイルの中身はダミーの文字列です。
試したプロジェクトの形は次のとおりです。
package.json {"name": ..., "version": "1.0.0", "main": "src/index.js"}
src/index.js
.env API_KEY=dummy...
.env.local
config/.env.production
config/secret.pem
.gitignore .env / .env.* / *.pem / node_modules/
1. .gitignore だけなら .env は入らない
.npmignore がないときは、npm は .gitignore の中身を使います(npm公式: 「.gitignore があり .npmignore がないときは、.gitignore の中身が使われる」)。
npm pack --dry-run
npm notice 58B package.json
npm notice 17B src/index.js
.env も鍵も入りませんでした。git リポジトリにしていないディレクトリでも同じ結果でした。
2. .npmignore を足すと .gitignore は使われない
同じプロジェクトに、test/ の1行だけの .npmignore を足しました。
npm notice 29B .env
npm notice 14B .env.local
npm notice 18B config/.env.production
npm notice 7B config/secret.pem
npm notice 58B package.json
npm notice 17B src/index.js
.gitignore の除外が効かなくなり、.env も鍵も入りました。npm publish --dry-run でも同じ一覧が出ました。
npm公式の「常に除外されるファイル」には .git・.npmrc・node_modules などが並んでいますが、.env は入っていません。.npmignore を作ったら、.gitignore と同じ除外をそちらにも書く必要があります。
# .npmignore
test/
.env
.env.*
*.pem
こう書くと、.env と鍵は入らなくなりました。
3. files にディレクトリを書くと、その中は丸ごと入る
package.json の files は「入れるもの」の一覧です(npm公式)。"files": ["src"] なら、入ったのは package.json と src/index.js だけでした。
一方、設定ファイルも配りたくて "files": ["src", "config"] と書くと、こうなりました。
npm notice 18B config/.env.production
npm notice 7B config/secret.pem
npm notice 82B package.json
npm notice 17B src/index.js
ルートの .gitignore には .env.* と *.pem を書いてありましたが、config/ の中では外れませんでした。npm公式には「ルートの .npmignore は files を上書きしないが、サブディレクトリの .npmignore は上書きする」とあります。実際に config/.npmignore に .env* と *.pem を書くと、2つとも入らなくなりました。
4. 公開前の確認
npm pack --dry-run
これで、公開されるファイルの一覧が送信なしで出ます。見るのは次の3点です。
-
.envで始まるファイルがないか -
*.pem・*.key・id_rsaなどの鍵ファイルがないか -
filesで丸ごと指定したディレクトリに、設定や秘密が混ざっていないか
もし公開してしまったら、パッケージを消すより先に、入っていた鍵を再発行してください(推奨。公開された時点で取得された可能性があるため)。
まとめ
-
.npmignoreを置くと.gitignoreは使われない(npm公式・実機)。.envは npm の既定の除外に入っていない(npm公式)。 -
filesにディレクトリを書くと、中の.env.productionや鍵も入った(実機)。サブディレクトリの.npmignoreで外せた(実機・npm公式)。 - 公開前は
npm pack --dry-runで一覧を見る。
AIエージェントの手元で .env が読めるかどうかは、ai-secret-check(npx github:supportapp3-lab/ai-secret-check scan、値は表示せず通信もしません)で点検できます。npm パッケージの中身はまだ点検対象ではありません。
関連記事:
- AIにコミットを任せる前に:.envと鍵をpre-commitで止める
- 過去にコミットした.envはgitの履歴から読める:見つけ方と git-filter-repo での消し方
- Codex CLIに.envを読ませない設定:公式例の "**/*.env" だけでは .env.local と深い階層が読めた
参考(公式):
※ 仕様は 2026-10-21 時点の npm 公式ドキュメントに基づきます。検証は npm 11.21.0 で、Linux の使い捨て環境でのみ行いました。
更新情報やちょっとしたTipsは X(@supportapp3_lab)で発信しています。