シークレットとAPIキー: 露出したキーの罠
シークレットとは、アクセス権を与えるもの全般を指す。(アプリケーション・プログラミング・インターフェース)キー、データベースパスワード、決済プロバイダのトークン、署名鍵。最もありふれていて——そして最も高くつく——バイブコーディングのミスは、これを漏らすことだ。
人々を絶えず捕らえる罠が2つある。
- クライアントコードの中のシークレット。 フロントエンド(ブラウザで動くJavaScript)にあるものはすべて公開だ。ユーザーはdev toolsを開いて読める。ReactコンポーネントからAPIを呼んでと頼まれたAIは、喜んでそこにあなたのシークレットキーを貼り付ける——そして今や、あなたのサイトを訪れた誰もがそれをコピーして請求額をつり上げられる。シークレットキーはサーバーに置くべきものであり、ブラウザに配信されるコードには決して置いてはいけない。
- リポジトリの中のシークレット。 ファイルにハードコードされたキーはにコミットされる。あとで削除しても、それはgitの履歴に永遠に残り、ボットはpushから数分以内にまさにこれを狙って公開リポジトリをスキャンする。
シークレットの正しい置き場所は環境変数だ——実行時にアプリに供給される値で、コードからは完全に切り離されている。
// VULNERABLE: キーがソースの中にあり、gitにコミットされてしまう
const stripe = new Stripe("sk_live_51H8xQ2eZvK...");
// SAFE: キーは環境から読まれ、コードには決して書かれない
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
シークレットには安全な住み家がただ一つあります — サーバー側で、環境から読み込むこと。ブラウザは公共の場です。そこへ出荷されたものは、開発者ツールを開く誰にでも読めます。
┌──────────────────────────────────────────┐
│ .env (gitignore済み・コミット禁止) │
│ STRIPE_SECRET_KEY=sk_live_... │
└───────────────────┬──────────────────────┘
│ 実行時に注入される
▼
┌──────────────────────┐ ┌──────────────────────┐
│ SERVER │ │ BROWSER(クライアント)│
│ process.env.KEY ✓ │ ✗──────│ 誰でも読める │
│ ここでStripe呼出 │ 禁止 │ dev tools · "view │
│ │ 送信 │ source" · network │
└──────────────────────┘ ここ └──────────────────────┘
安全: 非公開のまま 公開: = 漏洩する
シークレットを1つでも書く前に、.env(および .env.local など)を .gitignore に追加すること。もしキーがコードや履歴に一度でも入り込んだら、それは焼かれたものとして扱う。ローテーションする(新しいものを生成して古いものを失効させる)——行を削除するだけでは不十分だ。古いキーはまだ有効で、まだ世に出回っているのだから。