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?

Viteの.envはVITE_を付けるとビルドに入る:loadEnvの書き方次第でDB_PASSWORDもシェルの環境変数もdistに入った

0
Posted at

結論

  • Vite では VITE_ で始まる変数は、ビルドした JS(dist/)にそのまま入ります(Vite公式)。.env に VITE_API_KEY と書いてコードで参照すると、値が dist/assets/*.js に平文で入りました。.env.local に書いても同じでした(筆者の環境で確認)。
  • 接頭辞のない DB_PASSWORD などは、import.meta.env では入りません。ただし vite.config.js で loadEnv(mode, process.cwd(), '') の結果を define で process.env に丸ごと渡すと、.env の全部の値と、ビルドしたシェルの環境変数まで dist/ に入りました(筆者の環境で確認)。
  • フロントに置いた値は、閲覧者が誰でも読めます。秘密の鍵は VITE_ を付けずにサーバー側だけで使い、ビルド後に dist/ に .env の値が入っていないかを確かめます(確認用のスクリプトを最後に載せます)。

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

AIに作らせたフロントエンドで「APIキーは .env に入れたので安全」と考えてしまうことがあります。.env は Git には入れなくても、ビルドの結果に入れば公開した瞬間に誰でも読めます。どの書き方で入り、どの書き方なら入らないのかを Vite で確かめました。AIエージェントが実際にどの書き方をよく出すかは確かめていません。

検証環境と範囲

  • Debian 13.7 / Node.js 20.19.2 / npm 11.21.0 / Vite 8.3.5
  • npx vite build で dist/ を作り、ダミーの値が含まれるかを grep -r で調べました。公開やデプロイはしていません。
  • 値はすべてダミーの文字列です。

.env は次のとおりです。

VITE_API_KEY=DUMMY_VITE_KEY_0001
DB_PASSWORD=DUMMY_DB_PASS_0002
SECRET_TOKEN=DUMMY_SECRET_0003

1. VITE_ の変数は参照すると dist/ に入る

src/main.js
console.log(import.meta.env.VITE_API_KEY)
書き方 VITE_API_KEY DB_PASSWORD SECRET_TOKEN
import.meta.env.VITE_API_KEY を参照 入った 入らない 入らない
何も参照しない 入らない 入らない 入らない
console.log(import.meta.env) で丸ごと出力 入った 入らない 入らない
import.meta.env.DB_PASSWORD を参照 入らない 入らない(undefined) 入らない
.env.local に VITE_LOCAL=... を追加し丸ごと出力 入った 入らない 入らない

.env.local の VITE_LOCAL も入りました。.env.local は「Git に入れないファイル」であって、「ビルドに入らないファイル」ではありません。

Vite 公式も、VITE_ で始まる変数はビルド時にクライアントのコードに入るので、APIキーのような秘密情報を入れてはいけない、と書いています(Env Variables and Modes)。

2. envPrefix: '' は Vite が止める

接頭辞をなくして全部の変数を import.meta.env で使おうとすると、ビルドがエラーで止まりました。

vite.config.js
export default { envPrefix: '' }
Error: envPrefix option contains value '', which could lead unexpected exposure of sensitive information.

3. define で process.env に丸ごと渡すと、全部入る

process.env.XXX を使う古いコードを Vite で動かすために、次のように書く例があります。

vite.config.js
import { defineConfig, loadEnv } from 'vite'
export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd(), '')
  return { define: { 'process.env': JSON.stringify(env) } }
})
src/main.js
console.log(process.env.VITE_API_KEY)

参照しているのは VITE_API_KEY だけですが、dist/ には DB_PASSWORD と SECRET_TOKEN の値も入りました。define は process.env の場所に、オブジェクト全体を文字列として埋め込むためです(筆者の推測。結果は実機で確認)。

さらに、.env にない変数を付けてビルドしてみました。

HOST_ONLY_VAR=DUMMY_HOST_0005 npx vite build

DUMMY_HOST_0005 も dist/ に入りました。 loadEnv は .env を読んだうえで、すでに process.env にある変数のうち接頭辞に合うものを合わせます(Vite公式: loadEnv)。第3引数を '' にすると全部の変数が合うので、CI やサーバーでビルドすると、そこに設定されているトークンまで入るおそれがあります。

vite.config.js の書き方 VITE_API_KEY DB_PASSWORD シェルの変数
loadEnv(mode, cwd, '') を process.env に丸ごと 入った 入った 入った
同じ設定で、コードは process.env.NODE_ENV だけ参照 入らない 入らない -
loadEnv(mode, cwd)(既定の VITE_)を丸ごと 入った 入らない 入らない
'process.env.VITE_API_KEY' だけを define 入った 入らない -

process.env.NODE_ENV だけを参照したときは入りませんでした。ただし、コードのどこかで process.env をまるごと使うと入ります。AIにコードを足してもらううちに、そういう参照が増えることもあるので、丸ごと渡す書き方は避けるのが安全です。

4. ビルド後に dist/ を確かめる

.env の値が dist/ に入っていないかを、値を画面に出さずに調べるスクリプトです。プロジェクトのルートで、vite build のあとに実行します。

check-dist.sh
# .env* の各値が dist/ に入っていないかを、値を表示せずに調べる
for f in .env .env.*; do
  [ -f "$f" ] || continue
  grep -vE '^\s*(#|$)' "$f" | while IFS='=' read -r k v; do
    v="${v%\"}"; v="${v#\"}"
    [ ${#v} -ge 8 ] || continue
    grep -rlqF -- "$v" dist/ && echo "dist に入っている: $k($f)"
  done
done

3の設定で実行すると、次のように出ました。

dist に入っている: VITE_API_KEY(.env)
dist に入っている: DB_PASSWORD(.env)

8文字未満の短い値は、ほかの文字列と偶然一致しやすいので飛ばしています。シェルや CI の環境変数は調べないので、3の書き方をしている場合は設定のほうを直してください。

VITE_ の値が出るのは、公開してよい値(公開用のURLや、公開前提のキー)なら問題ありません。秘密の鍵が出た場合は、その鍵を使う処理をサーバー側(API や サーバーレス関数)に移し、すでに公開していたなら鍵を再発行します。

まとめ

  • VITE_ の変数は、参照すると dist/ の JS に平文で入る。.env.local でも同じ(実機・Vite公式)。
  • 接頭辞のない変数は import.meta.env では入らない(実機・Vite公式)。envPrefix: '' はエラーで止まる(実機)。
  • loadEnv(mode, cwd, '') を define で process.env に丸ごと渡すと、.env の全部とシェルの環境変数まで入った(実機)。
  • ビルド後に dist/ を調べる。秘密の鍵はサーバー側だけで使う。

AIエージェントの手元で .env が読めるかどうかは、ai-secret-check(npx github:supportapp3-lab/ai-secret-check scan、値は表示せず通信もしません)で点検できます。ビルド結果の中身はまだ点検対象ではありません。

関連記事:

参考(公式):

※ 仕様は 2026-10-22 時点の Vite 公式ドキュメントに基づきます。検証は Vite 8.3.5 で、Linux の使い捨て環境でのみ行いました。

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