APIキーをコードへ直接書いてはいけない理由

APIキーをコードへ直接書いてはいけない理由

前回の記事では、PythonからOpenAI APIを1回だけ呼び出しました。

そのときAPIキー(生成AIのサービスを使うための、パスワードのような文字列)はコードへ直接書かず、getpass() という関数を使って、プログラムを動かすたびに手で入力しました。

なぜ、わざわざそんな手間をかけたのでしょうか。次のように書いてしまえば、一見とても簡単です。

from openai import OpenAI

client = OpenAI(
    api_key="sk-xxxxxxxxxxxxxxxx"
)

この "sk-xxxxxxxxxxxxxxxx" の部分が、本物のAPIキーに当たります。実際のキーは英数字が数十文字続く長い文字列です(この記事では、すべてダミーの文字列に置き換えて掲載しています)。

しかし、この書き方には大きな問題があります。APIキーがPythonコードの一部になってしまうからです。

コードは、GitHubへ保存する、Notebookを共有する、同僚へ渡す、資料へ貼る、スクリーンショットを撮る──といった形で、思っている以上に簡単に外へ出ていきます。

そのときAPIキーまで一緒に出てしまうと、第三者があなたのアカウントとして生成AIのAPIを使える状態になります。料金はあなたに請求されます。

この記事は4部構成です。

  1. なぜ危険か — APIキーは何であって、漏れると何が起きるのか
  2. どこから漏れるか — 4つの経路と、自分の状況を調べる方法
  3. 漏れる前にやっておくこと — 被害を限定する設定
  4. 漏らしたかもしれないとき — 初動の5ステップ

「では、どこにキーを置けばよいのか」という具体的な設定手順は、次の記事で扱います。この記事は、その前に知っておきたい「なぜそうするのか」の部分です。

この記事を読み終えると、次のことができるようになります。

  • APIキーが「設定値」ではなく「認証情報」であることを、人に説明できる
  • 自分のコードや作業履歴にキーが残っていないか、コマンドで調べられる
  • 漏れても被害が限定されるように、先に金額の上限をかけられる
  • キーの権限を絞る・用途ごとに分ける、という考え方が分かる
  • 漏らした疑いがあるときに、何から手をつければよいか分かる
Screenshot

【月1 特定テーマ講座(11月)】
POS売上分析Copilotを作る
(POSデータ×PYTHON×生成AI)

【開催日時】 全2回(土)2026/11/7,11/21(13:30〜18:00)
【受講形式】 当日Zoom( or 復習用に後日動画視聴)
【参加費用】 2万2千円(税込み)/人

先に、この記事で出てくる用語を整理します

セキュリティの話は、用語が分からないだけで急に難しく感じます。この記事で使う言葉を、先にまとめておきます。

用語 この記事での意味
API(エーピーアイ) プログラムから外部のサービスを呼び出すための窓口。ここでは生成AIのサービスを指します
APIキー APIを使うときに添える、長い英数字の文字列。「誰の利用か」を示すパスワードのようなもの
認証情報 本人であることを証明する情報の総称。パスワードやAPIキーが該当します
SDK(エスディーケー) そのサービスを使いやすくするために配布されている部品集。ここでは pip install openai で入るPythonのライブラリのこと
環境変数 パソコンやサーバー側に保存しておく設定値。プログラムの外に置けるので、コードに書かずに済みます
Git(ギット) ファイルの変更履歴を記録するソフト。「いつ誰が何を変えたか」がすべて残ります
GitHub(ギットハブ) Gitの履歴をインターネット上に置いて共有できるサービス
リポジトリ Gitが履歴を管理している、プロジェクト1つ分の入れ物
commit(コミット) 変更内容を履歴として1件記録する操作
push(プッシュ) 手元の履歴をGitHubへ送る操作
Notebook コードと実行結果を1つのファイルにまとめて保存できる形式(.ipynb)。Jupyter NotebookやGoogle Colabで使います
ターミナル 文字でコマンドを打ってパソコンを操作する画面。WindowsならPowerShellやコマンドプロンプト、macOSならターミナル.app
ローテーション 古いキーを捨てて、新しいキーへ取り替えること

APIキーは「設定値」ではなく「認証情報」

APIキーは、APIを利用するときに使うアクセスコードです。

プログラムからAPIへ送るリクエスト(お願い)にキーを添えると、API側は「このアカウントからの利用だ」と判断して処理を実行し、その分の料金をそのアカウントへ計上します。

つまりAPIキーは、誰の権限でAPIを使うのかを示す秘密情報です。同じ「コードに書く文字列」でも、モデル名やファイル名とは性質がまったく違います。

model = "gpt-5.6-luna"

こちらは、どのAIモデルを使うかを指定しているだけの設定値です。公開されても、それだけで第三者があなたのアカウントを使えるわけではありません。

一方、APIキーが漏れると、第三者がそのキーでAPIリクエストを送れる状態になります。

OpenAIも、APIキーの漏えいは無断利用、予期しない料金、クォータ(あらかじめ決められた利用可能な量)の消費、APIアクセスの中断につながる可能性があると案内しています。

ひとことで言うと。APIキーは「設定」ではなく「鍵」です。設定はコードに書いてよく、鍵は書いてはいけません。

コードとキーが1つのファイルになると何が起きるか

問題は、先ほどのコードがPythonとして動いてしまうことではありません。

動くこと自体は正しいのです。問題は、コードとAPIキーが1つのファイルに同居していることです。

APIキーをコードへ直接書くと、どこから漏れるのか コードとAPIキーが1つのファイルになると、GitHubへのcommit、Notebookの共有、スクリーンショット、ブラウザやモバイルアプリへの埋め込みという4つの経路から外部へ出る。コードとキーが1つのファイルになると、どこへ流れるか1つのファイルにコード + APIキーapp.py / notebook.ipynb GitHubへ commit する公開リポジトリなら誰でも見られる Notebookを共有する出力セルにも残る スクリーンショット・ブログ画像の中に認証情報が写る ブラウザ・モバイルアプリ利用者側から取り出せる対策はひとつ。APIキーをコードから分離して管理する

ファイルが1つ外へ出れば、その中身は全部一緒に出ていきます。

コードを他の人に渡せば、APIキーも渡ります。GitHubへ保存すれば、APIキーも保存されます。Notebookを共有すれば、APIキーも共有されます。

「コードだけ渡す」ということができません。

 避けたい書き方と、分離した書き方

避けたいのは、キーをコードの中に置く書き方です。

# 避けたい書き方
from openai import OpenAI

client = OpenAI(
    api_key="sk-xxxxxxxxxxxxxxxx"
)

キーをコードから分離すると、こうなります。

# キーをコードへ書いていない
from openai import OpenAI

client = OpenAI()

後者にはAPIキーが1文字も出てきません。それでも、ちゃんと動きます。

理由は、OpenAIのPython SDK(pip install openai で入る部品集)が、OPENAI_API_KEY という名前の環境変数を自動的に探しに行くからです。

環境変数とは、プログラムの外側(パソコンやサーバー側)に保存しておく設定値のことです。コードには書かず、あらかじめパソコン側へ登録しておけば、SDKがそこから読み取ってくれます。

前回の記事で OpenAI() と書くだけで動いたのは、この仕組みによるものです。getpass() で入力したキーを環境変数へ入れていたので、SDKが自動的に拾っていました。

「なぜ api_key= と書かないのか」の答えが、これです。

 被害の上限を決めるのは誰か

ここで、少し立ち止まって考えてみてください。

キーが漏れて第三者に使われたとき、被害額を決めるのは「相手がどれだけ使うか」です。

こちらからは予測できませんし、止めることもできません。気づくまで使われ続けますし、気づくのは請求を見たときかもしれません。

だからこそ、自分で天井を決めておくという発想が必要になります。これは記事の後半「先に利用上限をかけておく」で扱います。

漏えい経路は主に4つ

実際にキーが外へ出てしまう経路は、大きく4つに分けられます。どれも特別なミスではなく、日常的な操作の延長線上にあります。

 経路1:GitHubへcommitする

特に注意したいのがGitHubです。

Gitはファイルの変更履歴を記録するソフト、GitHubはその履歴をインターネット上に置いて共有できるサービスです。

「変更を1件記録する」のが commit(コミット)、「手元の履歴をGitHubへ送る」のが push(プッシュ)です。

次のファイルをそのままcommitしてpushすると、APIキーもGitHubへ送られます。

公開リポジトリ(誰でも閲覧できる設定のプロジェクト置き場)なら、インターネット上の誰からでも見える状態になります。

# app.py
from openai import OpenAI

client = OpenAI(
    api_key="sk-xxxxxxxxxxxxxxxx"
)

OpenAIも、APIキーをリポジトリへcommitしないことを明確に推奨しています。

  「あとで消せば大丈夫」ではない

ここがこの記事でいちばん重要な部分です。

一度pushしたあとで api_key="..." の行を削除し、もう一度commitしたとします。

いま画面で見えているファイルからは、確かに消えています。

しかしGitは「変更の履歴」を記録するソフトです。行を消すと、履歴から前の内容が消えるのではなく、「この行を消した」という記録が1件追加されるだけです。

Gitは今のファイルと変更の履歴の両方を持っている 現在のファイルからAPIキーの行を消しても、Gitの過去のcommitには元の内容が残る。消す操作は「消した」という記録が増えるだけで、前の記録は消えない。行を消しても、Gitの履歴には残るあなたが今見ているファイル# app.pyclient = OpenAI()キーの行は消してある→ 一見、安全に見えるGitが持っている履歴1最初に書いたapi_key=”sk-xxxx…”ここに残る2別の修正をした(キーはそのまま)3キーの行を消した← 今のファイル「消す」は、消したという記録が1つ増えること。前の記録は消えないだから、一度でも書いてしまったキーは「消したから大丈夫」にはなりません。新しいキーへ取り替えます。

結果として、キーを書いた時点のcommitはそのまま残り続けます。

あとで説明するコマンドを使えば、誰でもその中身を取り出せます。

さらに、公開されていた時間に次のことが起きた可能性もあります。

  • 誰かが閲覧した
  • 自動でネット上を巡回するプログラム(クローラー)が取得した
  • リポジトリがfork(フォーク/他の人のアカウントへ複製)された
  • 誰かのパソコンへclone(クローン/手元へ丸ごとコピー)された

fork も clone も、コピーされた側の履歴には元のキーが入ったまま残ります。あなたが自分のリポジトリを直しても、コピーには手が届きません。

つまり、公開したAPIキーを後から画面上で隠すだけでは、安全とは言えません。

漏えいの可能性があるなら、古いキーを使い続けず、無効化して新しいキーへ切り替えます(=ローテーション)。

  .envcommit すれば同じ

環境変数を扱うとき、.env(ドット・イーエヌブイ)という名前のファイルへ設定値を書いておく方法があります。中身は次のような1行です。

OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxx

Pythonコード本体へ直書きするより管理しやすくなりますが、注意点があります。

.env ファイルそのものをGitHubへcommitしてしまえば、結局キーは漏れます。ファイル名が変わっただけで、中身は同じだからです。

そのため一般には、.gitignore(ギットイグノア)というファイルに .env と書いて、Gitの管理対象から外します。

.gitignore は「このファイルは履歴に含めない」という指示書です。

ただし「.gitignore に書いたから絶対安全」ではありません。すでにcommit済みのファイルは、あとから .gitignore へ追加しただけでは履歴から消えません。

.gitignore が効くのは、これから追加されるファイルに対してだけです。

 経路2:NotebookやColabを共有する

データ分析の現場では、GitHub以上にこちらのほうが身近かもしれません。

Notebookとは、コードと実行結果を1つのファイル(.ipynb)にまとめて保存できる形式で、Jupyter NotebookやGoogle Colabで使われています。

そのNotebookのセル(コードを書く1つの入力欄)へ、次のように書いたとします。

OPENAI_API_KEY = "sk-xxxxxxxxxxxxxxxx"

このNotebookを同僚へ送る、Google Driveで共有する、研修資料として配る、GitHubへアップロードする──いずれの場合もキーが一緒に共有されます。

しかもNotebookのファイルには、コードセルだけでなく、実行結果(出力セル)、Markdownのメモ、エラーログまでがまとめて保存されます。

画面上でスクロールして見えなくなっていても、ファイルの中には文字として残っています。「このセルだけは見えないだろう」と考えないほうが安全です。

 経路3:スクリーンショットやブログ記事

APIキーを画面に表示してしまうと、スクリーンショット(画面の撮影画像)経由でも漏れます。

たとえば、キーがちゃんと設定できたか確認しようとして、次のように書いてしまうケースです。

# これは避ける
print(os.environ["OPENAI_API_KEY"])

print() は、指定した内容を画面に表示する命令です。この1行で、APIキーがそのまま画面に出てしまいます。

この状態でブログへ画像を掲載する、社内資料へ貼る、SNSへ投稿する、エラー相談のため画面を共有する──と、画像の中に認証情報が焼き付いたまま残ります。

APIキーが正しく設定されたか確認したいときも、キー本体を表示する必要はありません。次のように書きます。

import os

print(os.getenv("OPENAI_API_KEY") is not None)

os.getenv("OPENAI_API_KEY") は環境変数の値を取り出す命令、is not None は「中身が空ではない」という意味です。

つまりこのコードは、キーの中身ではなく「キーが設定されているかどうか」だけTrue / False で表示します。

設定確認には、これで十分です。

 経路4:ブラウザやモバイルアプリへ埋め込む

JavaScriptで動くWebページの中へAPIキーを書いたり、スマートフォンアプリの中へ埋め込んだりすると、利用者側からキーを取り出される可能性があります。

これらは利用者の手元で動くプログラム(クライアントサイド)なので、中身を調べようと思えば調べられるためです。

OpenAIも、クライアントサイド環境へAPIキーを配置しないよう案内しています。

一般的には、次の形にします。

ブラウザ
  ↓
自分のバックエンド      ← APIキーはここに置く
  ↓
生成AI API

バックエンドとは、利用者からは中身が見えない、自分で管理しているサーバー側のプログラムのことです。

ブラウザはそこへお願いを出すだけで、APIキーには触れません。キーはサーバーの中だけに置いておく、という考え方です。

自分のコードにキーが残っていないか調べる

ここまで読んで「自分のリポジトリは大丈夫だろうか」と思われたはずです。

実際に確かめてみましょう。

以下のコマンドは、ターミナル(文字でコマンドを打つ画面。WindowsならPowerShell、macOSならターミナル.app)で、調べたいプロジェクトのフォルダへ移動してから実行します。

 Gitの履歴を調べる

# 1. いま作業ディレクトリにあるファイルを調べる
grep -rn "sk-" . --exclude-dir=.git

# 2. 過去のcommit履歴に、キーらしき文字列の追加・削除がないか
git log -S "sk-" --oneline --all

# 3. .env が誤ってGitの管理下に入っていないか
git ls-files | grep -i "\.env"

それぞれ、何をしているコマンドかを説明します。

コマンド 意味
grep ファイルの中から指定した文字列を探す道具。-r はフォルダの中を再帰的に(下の階層まで)、-n は見つかった行番号も表示する、という指定です。--exclude-dir=.git は履歴の保管場所そのものを検索対象から外す指定で、結果が読みにくくならないようにしています
git log -S "sk-" 過去のcommitを順に調べ、sk- という文字列が追加された、または削除されたcommitを探し出します。-S はそのためのオプション、--oneline は1件1行で簡潔に表示、--all はすべてのブランチ(作業の枝分かれ)を対象にする指定です
git ls-files いまGitの管理対象になっているファイルを一覧表示します。その一覧を grep へ渡して、.env という名前が混ざっていないか確認しています(| は「左の結果を右へ渡す」という記号です)

要点は2つ目の git log -S です。現在のファイルから消していても、履歴に残っていればここで見つかります。

先ほどの「あとで消せば大丈夫ではない」を、自分の手で確認できるコマンドです。ここで1件でもヒットしたら、そのキーは漏れた前提で扱ってください。

 Notebookの出力セルを調べる

grep -l "sk-" *.ipynb

-l は「該当した行の中身ではなく、ファイル名だけを表示する」という指定です。

*.ipynb は、そのフォルダにあるNotebookファイルすべてを意味します。

Notebookは実行結果も保存されるため、コードセルから消しても出力セルに残っていることがあります。画面で確認するのではなく、この方法でファイルの中身そのものを検索してください。

なお、検索文字列の sk- はOpenAIのキーを想定した例です。

他社のキーは先頭の文字(接頭辞)が異なるので、自分が使っているサービスのキーの形に合わせて読み替えてください。

 見つかったときの判断

判断はシンプルです。

履歴に1回でも入っていたら、そのキーはローテーションする(新しいキーへ取り替える)。

「たぶん誰も見ていない」「非公開のリポジトリだから」と考えたくなりますが、それは確認できない前提です。

取り替えるコストは数分ですが、放置したときのコストは請求額に跳ね返ります。手順は記事の後半「漏らしたかもしれないときの初動」のとおりです。

もうひとつ大事なこととして、「見つからなかった=安全」ではありません。

すでに送ったメール、配布したZIP、共有済みのスクリーンショットは grep できません。調べられるのは、いま手元にあるファイルだけです。

先に利用上限をかけておく

ここからは予防の話です。

「漏らさない」だけでなく「漏れても被害が限定される」ようにしておきます。

キーを守ることと、漏れたときの金額に天井をつけておくことは、別々の対策です。

使用量アラートと上限(hard limit)の違い アラートは通知するだけでAPIの通信は続く。上限は通知に加えてAPIを止め、429とspend_limit_exceededのエラーコードを返す。「通知するだけ」と「実際に止める」は別の設定使用量アラート しきい値の通知届く API の通信続く監視のための設定上限(hard limit) しきい値の通知届く API の通信止まる事故のときの天井上限に達すると、APIはこう返す429 organization_spend_limit_exceeded429 project_spend_limit_exceeded前回の「429 = レート制限」と同じ番号。エラーコードで見分ける※ 反映に多少のラグがあるため、実際の利用が設定額をわずかに超えることがあります(2026年9月11日時点)。

 アラートと上限(hard limit)の違い

OpenAIには、金額に関する仕組みが2つあります。名前が似ていますが、役割はまったく違います。

使用量アラート 上限(hard limit)
しきい値に達すると 通知が届く 通知が届く
APIの通信 続く 止まる
役割 監視 事故のときの天井

「hard limit(ハードリミット)」は、直訳すると「固い上限」です。アラートは知らせるだけで、止めてはくれません。

通知が来ても、寝ている間や休暇中で気づかなければ、使われ続けます。事故に備えるなら、必ず上限のほうを設定してください。

設定できる階層は2つあります。

階層 対象 設定場所
組織全体 組織内のすべてのプロジェクト Organization settings → Spend
プロジェクト単位 そのプロジェクトに課金される利用のみ Project settings → Limits → Spend

OpenAIの管理画面では、利用を「プロジェクト」という単位でまとめられます。

学習用、検証用、本番用と分けておけば、上限も別々にかけられます。

 上限に達すると何が起きるか

上限に達すると、APIリクエストは処理されず、次のエラーが返ります。

429  organization_spend_limit_exceeded
429  project_spend_limit_exceeded

429HTTPステータスコードと呼ばれる3桁の番号で、通信の結果を表します(うまくいったときは 200、ページが見つからないときは 404)。

429 は「リクエストが多すぎます」という意味です。その右側の英語が、より詳しい理由を示すエラーコードです。

ここで前回の記事との接続があります。

前回、429 は「レート制限」(短時間に呼びすぎたときの制限)として説明しました。同じ 429 が、金額の上限超過でも返ります。

番号だけでは区別できないので、右側のエラーコードを見てください。spend_limit_exceeded と書かれていれば、呼びすぎではなく金額の上限に達しています。

ひとつ注意点があります。

利用額の集計に多少のラグがあるため、実際の利用が設定額をわずかに超えることがあります。

「1円も超えない」仕組みではなく、「桁が変わる前に止まる」仕組みだと考えてください。それでも、上限なしで放置するのとは被害額が二桁変わります。

キーを用途ごとに分け、権限を絞る

上限と並ぶもうひとつの予防策が、キーそのものにできることを、あらかじめ減らしておくことです。

漏れたときに相手ができることは、そのキーに与えた権限の範囲までに限られます。

 チームで1つのキーを共有しない

次のような運用は避けたほうがよいでしょう。

チーム共通APIキー

Aさん ─┐
Bさん ─┼→ 同じキー
Cさん ─┘

OpenAIは、チームメンバー間でAPIキーを共有するのではなく、各メンバーが固有のキーを使うことを推奨しています。

1人1キーにすると、次の利点があります。

  • 誰の利用か分かる
  • 問題のあるキーだけ止められる(他のメンバーの作業は止まらない)
  • 人によって権限を変えられる
  • 利用状況を人ごとに追える

共有キーだと、1人が漏らしただけで全員のキーを取り替えることになります。

 プロジェクト単位のキーと権限

APIキーはプロジェクトごとに作成・管理でき、そのキーに与える権限レベルを3段階から選べます。

権限レベル できること
All すべてのエンドポイントを利用できる
Restricted エンドポイントごとに None / Read / Write を個別に設定できる
Read Only 読み取りのみ

エンドポイントとは、APIの機能ごとに用意された呼び出し先のことです。

「文章を生成する」「音声を文字にする」「ファイルを一覧する」などが、それぞれ別のエンドポイントになっています。

None は使えない、Read は読み取りだけ、Write は書き込みもできる、という指定です。

つまり、「このキーは文章生成を呼べるだけ。設定変更もファイル削除もできない」というキーが作れます。

漏れたときにできることの範囲は、キーの権限で決まります。権限を絞るのは、上限設定と並ぶ有効な予防策です。

プロジェクト単位では、ほかに次のものも制御できます。

  • モデルごとのレート制限
  • 支出上限(設定できるのは組織またはプロジェクトのOwner=管理者権限を持つ人のみ)
  • アクセスできるモデルの限定

 IPアドレスで制限する

OpenAIのAPIキー安全ガイドには IP allowlistingも挙げられています。

IPアドレスとは、インターネット上での住所にあたる番号です。

あらかじめ登録した住所からのリクエストだけを許可し、それ以外は拒否する仕組みが IP allowlisting です。キーが漏れても、相手のIPアドレスが登録されていなければ使えません。固定のサーバーから呼ぶ構成なら有効です。

一方、ノートPCから試す段階では、カフェや自宅など接続場所によって自分のIPが変わるため向きません。本番運用へ進むときの選択肢として覚えておいてください。

GitHub側の2つの防御

GitHubにも、秘密情報の流出を防ぐ仕組みが用意されています。

性格の違う2つがあり、片方は「入る前に止める」、もう片方は「入ってから見つける」です。

Push protection Secret scanning
タイミング push する前 push された後
動作 リポジトリに入る前にブロックする すでに入っている資格情報を検出する
位置づけ 予防 検出(最後の防御)

 Push protection:pushする前に止める

Push protectionは、APIキーらしき文字列を含むcommitがリポジトリへ入る前に、pushそのものを失敗させる機能です。

そもそも履歴に残らないので、前の章で見た「履歴から消えない」問題が発生しません。使えるなら、これを有効にしておくのがいちばん確実です。

 Secret scanning:履歴を含めて検出する

Secret scanningは、リポジトリの中にAPIキーやパスワードなどの機密情報が入っていないかを、GitHubが自動で検査する機能です。

  • 公開リポジトリでは無料で自動的に実行される
  • Git履歴の全ブランチを対象にする(過去のcommitまで遡って検査される)
  • コードだけでなく、Issueの説明文、Pull Requestのコメント、Wiki、Discussions も対象

3つ目は見落とされがちです。

Issue(課題の記録)やPull Request(変更の提案)は文章を書く場所ですが、そこにエラーログを貼ったときにキーが混ざることがあります。「コードにさえ書かなければよい」わけではありません。

ただし、「Secret scanningがあるからcommitしてよい」という意味ではありません。

検出は最後の防御であって、検出された時点ですでに履歴には入っています。

基本は、最初からコードへ秘密情報を入れないことです。

3社でキー管理はどう違うか

前回、OpenAI・Gemini・Claudeの最小コードを並べました。キーの扱いも見ておきます。

3社の環境変数名 OpenAIはOPENAI_API_KEY、Google GeminiはGEMINI_API_KEY、Anthropic ClaudeはANTHROPIC_API_KEY。3社ともSDKが環境変数から自動で読むため、環境変数に置く対策はどのサービスでも通用する。3社とも、SDKは環境変数からキーを読むOpenAI環境変数名OPENAI_API_KEYGoogle Gemini環境変数名GEMINI_API_KEYAnthropic Claude環境変数名ANTHROPIC_API_KEYだから「キーを環境変数に置く」対策は、どのサービスでもそのまま通用するコードに書かなくても、SDKが勝手に読んでくれる※ 管理画面の場所、権限設定の粒度、上限設定の有無は各社で異なります。利用前に公式ドキュメントで確認してください。

3社とも、SDKが環境変数から自動的にキーを読む設計になっています。

読みに行く環境変数の名前がそれぞれ決まっていて、そこに値が入っていれば、コードにキーを書かなくても動きます。

前回のコードが OpenAI() だけで動いたのも、この仕組みです。

ここから言えることは単純です。「キーを環境変数に置く」という対策は、どのサービスでもそのまま通用します。サービスを乗り換えても、覚え直すのは環境変数の名前だけです。

一方で、管理画面の場所、権限設定の細かさ、上限設定の有無は各社で異なります。

この記事で扱った上限や権限の話はOpenAIで確認したものなので、他社を使う場合は各社の公式ドキュメントなどで確認してください。

漏らしたかもしれないときの初動

ここが最も重要です。

「漏れたかもしれない」という段階で、本当に使われた証拠が出るまで待つのではなく、先に対応します。

キーを取り替えるコストは数分です。待って様子を見る理由がありません。

APIキーを漏らしたかもしれないときの初動 古いキーを無効化し、新しいキーを作り、Usageを確認し、公開箇所を清掃し、原因を直す。証拠を待たず疑った時点で動く。漏らしたかもしれないときの初動「本当に使われた証拠」を待たない。疑った時点で動く 1古いキーを無効化する最優先。まず使えない状態にする 2新しいキーを作るコードへ直書きせず、環境変数へ置く 3Usage を確認する身に覚えのない利用、急な増加、予期しない料金 4公開箇所を清掃する現在のファイル、Git履歴、共有Notebook、配布物5原因を直す直書き→環境変数、共有キー→個別キー一度外へ出た可能性のあるキーは、履歴を消しても復活させない

 Step 1:古いキーを無効化する

まず、漏れた可能性のあるキーを使えない状態にします。

相手に使われる時間を短くすることが、被害を減らす最短の手段です。OpenAIのAPIキーは API Keys 画面で管理できます。

https://platform.openai.com/api-keys

公式ヘルプでは、対象キーを削除するとそのキーは使用できなくなると案内されています。

注意点として、そのキーを何かのアプリケーションが使っている場合、削除するとそのアプリはAPIへ接続できなくなります。

止まって困るものがあるかを先に把握したうえで、削除し、続けて新しいキーへ差し替えます。とはいえ、迷って放置するくらいなら止めてください。

 Step 2:新しいキーを作る

古いキーを止めたら、新しいキーを作成して必要な環境へ設定します。

このとき、またPythonファイルへ直接書いてはいけません。同じ経路でもう一度漏れます。

環境変数やSecret管理(クラウドサービスが提供する、秘密情報の保管機能)へ移行します。

 Step 3:Usageを確認する

OpenAIは、キーの漏えいが疑われる場合に利用状況を確認することも推奨しています。

Usage(ユーセージ)は管理画面にある利用状況のページで、いつ・どれだけAPIが使われたかを確認できます。見るのは次の点です。

  • 身に覚えのないAPI利用
  • 通常より急に増えた利用量
  • 予期しない料金

問題が疑われる場合は、早めにOpenAI Supportへ連絡します。

 Step 4:公開箇所を清掃する

キーを止めることが最優先です。そのあとで、キーが残っている場所を確認して片付けます。

  • GitHubの現在のファイル
  • Gitの過去履歴
  • 共有Notebook
  • 配布ZIP、社内資料
  • ブログ画像、スクリーンショット

ここで大事なことがあります。

Git履歴から秘密情報を取り除く作業をしても、古いキーを復活させて使ってはいけません。

履歴を書き換えても、すでにコピーされた分までは追えないからです。一度外部へ出た可能性のある認証情報は、必ずローテーションします。

 Step 5:原因を直す

最後に、なぜ漏れたのかを直します。

コードへの直書き
      ↓
環境変数

共有キー
      ↓
利用者ごとのキー

目視だけの確認
      ↓
Push protection + Secret scanning

漏えい対応は「キーを消して終わり」ではありません。同じ経路から次のキーが漏れないようにするところまでがセットです。

ここを飛ばすと、数か月後に同じことが起きます。

 OpenAI側で自動的に無効化される場合もある

OpenAIのヘルプには、公開インターネット上やアプリストア内のアプリでAPIキーの漏えいを検出した場合、そのキーは直ちに無効化されると記載されています。

これは利用者を守るための機能ですが、「OpenAIが見つけてくれるまで待つ」のではなく、自分で気づいた時点で止めてください。

検出されるかどうかは、どこにどう公開されたかによります。検出されない置き場所もあります。

共有する前のチェックリスト

コードやNotebookを誰かに渡す前に、次を確認してください。

APIキーの漏えいを防ぐ、共有する前のチェックリスト コード、GitHub、Notebook、運用の4カテゴリで、共有前に確認すべき項目をまとめたチェックリスト。共有する前のチェックリストコードapi_key=”…” と書いていないキーの値をコードに埋めていないパスワードやトークンも書いていないGitHub.env を commit していない.gitignore を確認したpush 前に差分を確認した履歴も grep で確認したNotebookセルへ直接書いていないprint でキーを表示していない出力セルにも残っていない共有前に全セルを確認した運用キーを他人と共有していない用途ごとにキーを分けている利用上限を設定してあるUsage を定期的に見ている1つでもチェックが外れたら、共有する前に直す

1つでもチェックが外れたら、共有する前に直します。

特に「履歴も grep で確認した」と「利用上限を設定してある」の2つは、この記事で新しく加えた項目です。

前者は「いま漏れていないか」、後者は「これから漏れたときにいくらで止まるか」を担保します。

まとめ

APIキーは単なる設定値ではなく、あなたの権限でAPIへアクセスするための認証情報です。

コードへ直接書くと「コードを共有する=APIキーも共有する」になってしまいます。

やること
漏らさない キーをコードから分離する。GitHub・Notebook・スクショ・クライアントサイドに注意
今を確認する git log -S で履歴を調べる。1回でも入っていたらローテーション
被害を限定する 上限を設定する。キーを用途ごとに分け、権限を絞る
漏らしたら 無効化 → 新規作成 → Usage確認 → 清掃 → 原因を直す

そして最も基本的な対策は、コードとAPIキーを分けて管理することです。難しい技術は必要ありません。「書かない」と決めるだけです。