非技術者向けに解説する API キーの環境変数運用:プロンプトやリポジトリにキーを残さない、dev/staging/prod をラベルで分ける、そして安全にローテーションする方法。

APIキーは、あなたのアプリがやり取りするサービス(決済、メール、地図、AI、分析など)へのパスワードのようなものです。サービスに対して「このリクエストは自分のアカウントから来ている」と伝え、課金や制限、アクセス許可が適用されます。
キーが漏れるのは、たいていコピー&ペーストで済ませてしまうからです。チャットに貼ったり、設定ファイルやメモに "とりあえず" と入れておくと、本来共有したくない場所に残ってしまいます。
よくある誤って漏れる経路は、チャットプロンプト(特に速く開発しているとき)、リポジトリへのコミットやレビュー用の zip アップロード、スクリーンショットや画面録画、共有ドキュメントやチームチャット、あるいは誰でも見られるフロントエンドにハードコードすることです。
リスクは抽象的ではありません。まず速攻で来るのが意外な請求です:誰かがあなたのキーで大量に API を呼び出せば料金が発生します。次にデータアクセスのリスク:そのキーで顧客データを読めたりメールを送れたりするなら、攻撃者も同じことができます。最悪の場合、広範な権限を持つキーは新しいキーを作るなどアカウント乗っ取りにつながります。
セキュリティの専門家でなくても、ほとんどの効果は習慣の小さな変更で得られます:キーを "シークレット" と扱い、プロンプトやリポジトリから遠ざけること。まさに環境変数はそのための仕組みです:秘密は保護された場所に置き、アプリが実行時に読み取る。コードやスクリーンショットに埋め込まないようにします。
覚えるべきルールは一つだけ:コードはアプリの動作、設定は振る舞い、シークレットは決して公開してはいけないもの。
コード はあなたが作って配るロジック(画面、ボタン、計算、API 呼び出し)です。チームと共有して問題ないようにリポジトリに入ることが多いです。
設定(Config) は公開されても被害が出にくい値です。アプリ名、動作するリージョン、フラグ、サービスのベースURLなどが該当します。見られてもお金を使われたりプライベートデータにアクセスされたりするべきではありません。
シークレット は王国の鍵です:APIキー、DBパスワード、プライベートトークン、署名キーなど。第三者に渡るとアプリとして振る舞えてしまいます。
環境変数は、アプリが実行時に読むラベル付きのスロットに過ぎません。コードは STRIPE_SECRET_KEY のようなラベルを探し、そのとき設定されている値を使います。この分離こそが、環境変数が API キーに向く理由です:コードは変えずに、シークレットの値だけを外に置けます。
コードとシークレットを分けておくと、修正も容易です。もし誤って露出したら、コードを変更せずに値だけ差し替えられます。
実務的な考え方は:同じラベル、異なる値。
例として、PAYMENTS_KEY というラベルをどこでも使い、dev はテストキー、staging は制限付きキー、prod はフルの本番キーを使う、という運用ができます。Koder.ai のようなプラットフォームでデプロイすると、同じアプリを環境ごとに異なる環境設定で動かせます。
シークレットとは、他人が持つと不正に権限を行使できる値です。見知らぬ人がそれを得るとログイン、課金、データ参照、アプリの偽装などができてしまいます。
一般的なシークレットは API キー、データベースパスワード、アクセス用のプライベートトークン、署名キー、Webhook シークレットなどです。作成・削除・課金・読み取り・署名ができるものはシークレット扱いしてください。
見た目は harmless(無害)でも実は危険な値がよくあります。書き込み可能なトークンは典型的な落とし穴です。長いランダムな文字列に見えても、攻撃者が変更やアップロード、メール送信、データベース書き込みをできてしまうことがあります。管理者キー、サービスアカウントの JSON ファイル、長いトークン類も同様です。
すべてをシークレット扱いする必要はありません。通常シークレットでないものは、機能フラグ(UIや挙動を変えるだけ)、公開URL、表示用テキスト、解析の測定ID、単独ではデータにアクセスできない内部IDなどです。フロントエンドやドキュメントに表示されることを前提とした値は大抵シークレットではありません。
簡単なテスト:それが公開チャットに貼られたり公開リポジトリにコミットされたら気が済まないなら、それはシークレットです。
使うシークレットを小さなリストに書いておきましょう。それぞれ何に使うか(決済、メール、DB、ストレージ)、どの環境に置くか(dev/staging/prod)、誰が所有者か(あなた、チームメンバー、ベンダー)、読み取り専用か書き込み可かをメモします。後でキーをローテーションする際にこのリストが役立ちます。
多くの漏洩は「ハッカー」によるものではなく、誰かが値をコピーしてそのまま見える場所に残す通常の瞬間です。検索できたり同期されたり転送されたり画面共有されたりするものは公開される可能性があると考えましょう。
チャットは大きな原因です。助けを求めるときに人は API キーを丸ごと貼りがちですが、チャットは保存や共有されます。助けが必要な場合は、キーの最後の4〜6文字とキー名だけを貼る(例:STRIPE_SECRET_KEY ...9f2a)などにしましょう。
Git は古典的な罠です。一時的にファイルにキーを追加してコミットし、後で削除してもコミット履歴に残ります。フォークやコピーされたスニペット、プルリクの差分を通じて広がることもあります。
スクリーンショットや画面録画は想像以上に漏れます。デモ動画が設定画面やターミナル、トークンを含むエラーメッセージを写すことがあります。ぼかしでも他の情報から復元されうる場合があります。
課題管理やメモアプリも静かな漏洩源です。チケットやチェックリスト、共有ドキュメントはチームやベンダー間でコピーされます。公開ログのように扱いましょう。
いくつかの習慣がほとんどの漏洩を防ぎます:
Koder.ai で開発しているなら同じ考え方を適用してください:機密値はチャットではなく環境設定に置きます。
目的はシンプルです:アプリはプロンプトやコード、Git に残るファイルからではなく、環境からシークレットを読み取るようにすること。
.env ファイルを使う(ただし Git に入れない).env はマシン上のプレーンテキストファイルで、キーと値を保存します。ローカルセットアップが簡単になる一方で漏れやすいので財布のように扱ってください。
ローカルに .env を作り、必ず Git の無視設定(.gitignore)に追加します。変数名をチームと共有する必要がある場合は、実際の値を入れないプレースホルダだけの .env.example を共有してください。
誰が見ても用途がわかる明確な名前にします:
OPENAI_API_KEYSTRIPE_SECRET_KEYDATABASE_URLSENDGRID_API_KEYS3_ACCESS_KEY_ID良い名前は dev/staging/production を設定するときのミスを減らします。
アプリ起動時に OS に対して「OPENAI_API_KEY の値はあるか?」と確認します。値があればそれを使い、なければ明確なエラーで早期に失敗するべきです。
実用的な習慣としては、変数の存在(はい/いいえ)だけをログに残し、シークレットそのものは絶対に出力しないことです。
チャットにキーを貼らないでください。パスワードマネージャ(共有ボールト)や別の安全なチャネルを使い、必要なものだけを共有します。離職した人がいる場合はキーをローテーションしてください。
例:創業者が Koder.ai のプロジェクトをエクスポートしてローカルで実行する。.env は自分のラップトップに置き、.env.example のみをコミットし、実際のキーは共有パスワードマネージャでチームに渡す、という流れです。
環境を三つの別の部屋だと考えてください。
Dev はあなたのラップトップや個人用サンドボックス。頻繁に変更します。Staging は本番に近い挙動を確認する安全なコピーで、顧客に影響を与えないようにします。Prod は顧客が使う実際の環境です。
基本ルール:変数名はすべての環境で同じにし、値だけを変える。コードはどの環境でも STRIPE_SECRET_KEY を読みに行き、各環境がそれぞれ異なる値を提供します。
簡単なマッピング表(メモでも良い)を作ると便利です:
| 変数名(どこでも同じ) | Dev の値 | Staging の値 | Prod の値 |
|---|---|---|---|
PAYMENTS_API_KEY | テストキー | ステージング用キー | 本番キー |
APP_BASE_URL | localhost の URL | staging のドメイン | custom ドメイン |
DATABASE_URL | ローカル DB | ステージング DB | 本番 DB |
Prod に Dev のキーを再利用してはいけません。Dev キーはチーム間で共有されることが多く、権限が広い場合があります。
小さなチームで環境値を整理するためのルール例:
STRIPE_KEY と STRIPE_API_KEY を混在させない)。Koder.ai のようなホスト型ビルダーを使う場合、各デプロイ対象(dev/staging/prod)を別の環境として扱い、同じコードに対して異なるシークレット値を設定します。
ローテーションとは、計画的に API キーを置き換えることです。正しくやれば、ローテーションは退屈なくらい簡単です:キーを入れ替え、動作を確認してから古いキーを無効にします。
安全な考え方は「短期間、二つのキーを共存させる」です。多くのサービスは複数アクティブなキーを許可するため、その重なりの間に設定を切り替えるとダウンタイムを避けられます。
シンプルなローテーションの流れ:
.env、ホスティング設定、プラットフォームの環境設定など)。プロバイダが複数キーをサポートしない場合は、トラフィックの少ない時間帯に短い停止を受け入れてローテーションします。目標は同じ:コードに触らずに1箇所で秘密を切り替えることです。
キーが漏れたと思ったら、まず行動し、その後に調査します。まずキーを取り消すか無効化し、新しいキーを発行して環境変数を更新します。アプリが安定したら、どこから漏れたか(チャットプロンプト、ビルドログ、スクリーンショット、古いコミット、共有ドキュメント)を調べて根を断ちます。
例:Koder.ai で小さな CRM を作り、メール API を使っているとします。新しいメールキーを生成し、アプリの環境設定にセットしてテストメールを送信、問題なければ古いキーを取り消します。
CI/CD はコードをビルドしてデプロイする自動化パイプラインで、ここでもアプリが必要とするシークレットを扱う必要があります。
主なルールは:APIキーをビルドログやソースコード、チャットプロンプトに紛れ込ませないこと。パイプラインも別のコンピュータとして扱い、制御された方法でのみシークレットを渡します。
ビルド時にだけ必要なシークレット(プライベートパッケージのダウンロードなど)と、デプロイ後に必要なランタイムシークレット(Stripe での請求やメール送信など)を分けてください。可能ならランタイム専用にすることで、シークレットがバンドルに埋め込まれたり、アーティファクトにキャッシュされたり、ビルド出力に出てしまうリスクを減らせます。
簡単な自己チェック:そのシークレットがユーザーのブラウザで必要なら、それはシークレットではありません。ブラウザで見える「公開鍵」は問題ない場合がありますが、サーバー用の API キーはサーバーに置いてください。
ホスティングプラットフォームの環境ごとのシークレットストレージを使い、dev/staging/prod で値を分けてください。
Koder.ai ホスティングでデプロイするなら、環境ごとに環境変数としてシークレットを設定し、コードや設定ファイルに貼らないようにします。アプリはランタイムでそれらを読み込みます(例:本番の PAYMENTS_API_KEY とステージングのテストキー)。
本番の安全を保つために、prod のシークレットを見られる人を限定し、デプロイ権限とシークレット編集権限を分けられるなら分けてください。また環境ごとに別のキーを使うことで、staging が prod データにアクセスできないようにします。
多くの漏洩は日常のショートカットが癖になって次のプロジェクトにも持ち越されることで起きます。
.env をコミット)してしまうキーがソースに入っているとバックアップやスクリーンショット、共有 zip、git 履歴に残ります。
対処:
.env を .gitignore に追加する。実際のキーをチャットに貼ると、そのテキストがどこに保存・共有されるかわかりません。vibe-coding ツールのチャットに全部放り込みたくなりますが、代わりに PAYMENTS_API_KEY=REDACTED のようなプレースホルダにして症状を説明しましょう。
良い習慣は、エラーメッセージをコピーして資格情報はコピーしないことです。
一つのキーを dev/staging/prod で使うと、1回の漏洩が大きな事故になります。チームで同じキーを共有していると、誰が使ったか追跡できません。
対処:環境ごとにキーを分け、可能ならユーザーやアプリごとにキーを分ける。
起動時に「全部の設定」を出力するとトークンを含んでしまうことがあります。
対処:必要最小限だけログに出し(例:Stripe key loaded: yes)、どうしても識別が必要なら値をマスクして最後の4文字だけ表示するなどにする。
例:ステージングが失敗しているときにフルキーを出力する代わりに STRIPE_KEY ending in 9K2P のようにして、正しいキーがデプロイされているかを確認できるようにする。
リリース前にシークレットだけに絞った落ち着いたチェックを一度行ってください。
api_key、secret、token、プロバイダ名などで検索し、共有ドキュメントやスクリーンショットも確認する。もしコミットやドキュメントに一度でも現れたらそのキーは焼かれた(使えない)と考え、置き換える。例:アプリが決済APIとメールAPIを使うなら、それぞれ dev/staging/prod 用にキーを用意し、明確なオーナーを付ける。デプロイ時は環境変数をその環境にマッピングし、チャットやコードにコピーしない。
Maya は非技術系の創業者で、ユーザーが購読を支払い、領収書やパスワードリセットをメール送信するシンプルなウェブアプリを作っています。彼女はプロンプトやリポジトリをきれいに保つため、シークレットをコードの外に置き、環境変数で実行時に注入する運用をしています。
彼女が定義する小さな実用的な環境変数群(名前はどこでも同じ、値だけ変わる)例:
APP_ENV = development / staging / productionAPP_BASE_URL = http://localhost:3000 / https://staging.example.com / https://example.comPAYMENTS_PROVIDER_SECRET_KEY = テストキー(dev) / テストキー(staging) / 本番キー(prod)EMAIL_PROVIDER_API_KEY = サンドボックスキー(dev) / 制限付きキー(staging) / フルキー(prod)DATABASE_URL = ローカル DB(dev) / ステージング DB(staging) / 本番 DB(prod)シンプルなルール:dev と staging はテストモードと分離したデータを使い、production は本番キーと実データを使う。こうすれば staging のミスで実際のカードに課金されたり実顧客にメールが届いたりしません。
現実的なローテーション事例:外注スタッフがアクセス権を持っていて退職したとします。Maya は古いキーが漏れている可能性を考え、決済とメールの新しいキーを作成して各環境の値を更新します。まず本番を静かな時間帯にローテーションし、サインアップや決済、メール送信が問題ないことを確認してから staging と dev を更新します。問題があれば以前の既知の正常な設定にすばやくロールバックします。
後で面倒にならないための次のステップ:
すでに Koder.ai(koder.ai)で開発しているなら、デプロイや環境設定を一箇所で管理できるので整理がしやすく、スナップショットとロールバック機能は設定変更で障害が起きたときの復旧に便利です。
APIキーは短時間で膨大な請求を生むことがあり、場合によっては顧客データの参照やメール送信などの操作ができてしまいます。パスワードと同じように扱い、他人に渡らないようにしましょう。
シークレットを環境変数に入れておけば、値はコードやプロンプトに残りません。アプリはランタイムで STRIPE_SECRET_KEY のような名前を参照して値を読み込みます。コード自体は共有しても安全なままにできます。
他人が金を使えたり、プライベートなデータにアクセスできたり、アプリを偽装できるものはシークレットです。APIキー、データベースパスワード、プライベートトークン、署名キー、Webhookシークレットなどはシークレット扱いにしてください。公開される ID や UI 専用の設定は通常シークレットではありません。
チャットプロンプト、チームチャット、チケット、スクリーンショット、git コミット(履歴含む)が最も多い漏洩経路です。検索・同期・転送・画面共有できるものは公共化する可能性があると考えましょう。
ローカルでの .env ファイルは利便性が高い反面漏れやすいので、機密値は入れておいても構いませんが決してコミットしないでください。変数名だけ分かるようにプレースホルダだけの .env.example をコミットしましょう。
すべての環境で変数名を同じにして値だけ変えるのが基本です。例えば PAYMENTS_API_KEY を dev/staging/prod 全てに用意し、dev ではテストキー、prod では本番キーを使います。
いいえ。サーバー用の API キーはフロントエンドに入れてはいけません。ブラウザで誰でも読めてしまうためです。必要ならフロントから自分のバックエンド経由で安全に呼び出してください。
まず新しいキーを発行し(古いキーはすぐ削除しない)、環境変数を更新してアプリを再起動/デプロイします。本番のワークフローを実際に確認してから、古いキーを無効化します。プロバイダが複数キーを許す場合は短期間重複させると安全です。
露出したと思ったらまずそのキーを取り消すか無効化し、新しいキーを発行して環境設定を更新・デプロイします。安定したら、どこから漏れたか(チャットログ、コミット、スクリーンショットなど)を調べて根本原因を取り除きます。
環境ごとの設定でシークレットを保存し、プロジェクトのチャットやソースコードには入れないでください。設定変更で問題が起きたらスナップショットやロールバックで既知の正常状態に戻し、リークしたキーを再導入しないようにします。