2026年5月20日、GitHubは、攻撃者が約3,800の内部コードリポジトリからデータを盗んだことを確認しました。侵入経路はGitHubサーバーのゼロデイではなく、従業員のノートパソコンにインストールされた不正なVS Code拡張機能でした。拡張機能は開発者と同じファイルシステム権限で動作するため、ソースコード、設定ファイル、ワークスペース内の認証情報を読み取れます。APIキーを同種の攻撃から守るには、クラウドだけでなく、開発者マシンとそこで動くツールを前提に対策する必要があります。
TL;DR(要するに)
侵害されたIDE拡張機能や流出したリポジトリからAPIキーを守るには、開発ツールが読める場所にアクティブな認証情報を置かないことが重要です。
実施すべきことは次の通りです。
- シークレットをソースコードにハードコードしない
- 実キー入りの
.envをコミットしない -
.gitignoreをセキュリティ制御として扱わない - キーを環境ごとに分離する
- 最小権限・短命の認証情報を使う
- 定期的にローテーションする
- APIクライアントでは、プレーンテキストファイルではなく環境変数やローカル値を使う
Apidogのようなツールを使うと、API認証情報をリポジトリやワークスペース内のプレーンテキストではなく、環境変数やローカル専用値として扱いやすくなります。
なぜGitHubの侵害はすべての開発者にとって警鐘なのか
GitHubのインシデントは、典型的なサプライチェーン攻撃です。TeamPCPとして追跡されている脅威グループは、npm、PyPI、PHPエコシステムでトロイの木馬化されたパッケージを使ってきた経緯があります。今回は、悪意のあるペイロードがVS Code拡張機能経由で侵入しました。
TechCrunchの報道によると、攻撃者は約3,800の内部リポジトリからデータを持ち出し、アンダーグラウンドフォーラムで5万ドル以上で販売しているとされています。GitHubは、これらの内部リポジトリ外に保存された顧客データが影響を受けた証拠はないと述べており、調査は継続中です。
ここで重要なのは、VS Code拡張機能が「単なるコード」だという点です。インストールすると、ユーザー権限でエディタプロセス内で実行されます。つまり、次のようなことが可能です。
- ディレクトリを一覧表示する
- ファイルを開いて読む
- ファイル変更を監視する
- 外部ネットワークへリクエストする
これは脆弱性ではなく、拡張機能モデルの通常動作です。多くの拡張機能は正当にファイルアクセスを必要とします。問題は、悪意のある、または侵害された拡張機能も同じ権限を使えることです。
典型的なプロジェクトでは、攻撃者が次のようなファイルを探します。
- リポジトリルートの
.env config/secrets.yml- テスト用スクリプトに残ったハードコード済みトークン
~/.aws/credentials- 認証トークン入りの
.npmrc - SSHキー
- CI/CDやクラウド、AIツール関連の認証情報
TeamPCPは、「Mini Shai-Hulud」npmワームキャンペーンの背後にいる攻撃者でもあり、感染したマシンから開発者、CI/CD、クラウド、AIツール関連の認証情報を収集しました。パターンは同じです。開発者マシンでコードを実行させ、認証情報らしきものを探します。
同様の露出パターンは、Vercel侵害から得られたAPIセキュリティの教訓や、npmサプライチェーンセキュリティガイドでも扱われています。
今確認すべき問いはシンプルです。
もし今、自分のエディタで悪意のある拡張機能が実行されたら、何が持ち出されるか?
ハードコードされたキーとコミットされた .env は常に負債になる
多くの認証情報漏洩は高度な攻撃ではありません。原因は単純です。
- 開発者が「一時的に」コードへキーを貼り付けた
-
.envファイルを誤ってコミットした - テストスクリプトに本番トークンを残した
- Git履歴から削除したつもりでローテーションしていない
たとえば、次のようなコードです。
import requests
# paymentsエンドポイントのクイックテスト
STRIPE_KEY = "sk_live_51Qk2mNExampleKeyDoNotShipThis"
response = requests.post(
"https://api.stripe.com/v1/charges",
auth=(STRIPE_KEY, ""),
data={"amount": 2000, "currency": "usd", "source": "tok_visa"},
)
print(response.json())
この sk_live_ キーは、すでにファイルの一部です。ワークスペース内にあるため、任意の拡張機能が読み取れます。さらにコミットされると、後で行を削除してもGit履歴に残ります。
.env はハードコードよりは良い方法です。たとえば次のように、実行時に読み込む形にできます。
# .env (実行時にロードされ、出荷されることを意図しない)
DATABASE_URL=postgres://app_user:Zk7%2BqN9wLx@db.internal:5432/payments
STRIPE_SECRET_KEY=sk_live_51Qk2mNExampleKeyDoNotShipThis
OPENAI_API_KEY=sk-proj-aB3dEf9hKlMnOpQrStUvWxYz1234567890
AWS_ACCESS_KEY_ID=AKIA4EXAMPLE7QRSTUVW
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
JWT_SIGNING_SECRET=8f2a91c4e7b6d3508f2a91c4e7b6d350
ただし、.env は万能ではありません。ファイルは依然としてワークスペース内にプレーンテキストで存在します。悪意のある拡張機能にとって、シークレットが app.py にあるか .env にあるかは重要ではありません。どちらもファイルであり、読み取れます。
.env が解決するのは、「シークレットをソースコードから分離する」問題です。しかし、次の問題は解決しません。
-
.envがコミットされる問題 - ローカルツールが
.envを読む問題 - Git履歴に残ったシークレットの問題
- 本番キーが開発者マシンに存在する問題
コミットされた .env は特に危険です。開発者が .env.example をコピーして .env を作り、本番キーを入れたあと、git add . で一緒に追加してしまうケースは珍しくありません。リポジトリが公開、ミラー、侵害された時点で、そのキーは漏洩したものとして扱うべきです。
リポジトリ漏洩の観点は、APIドキュメントとGitリポジトリのセキュリティでも詳しく解説されています。
.gitignore はセキュリティ制御ではない
.gitignore に .env を追加すると、守られているように感じます。しかし実際には、.gitignore は「このファイルを拾わないでください」というGit向けの指示にすぎません。
.gitignore が行うことは限定的です。git add 実行時に、パターンに一致する未追跡ファイルをスキップします。それだけです。
重要な失敗モードは3つあります。
1. すでに追跡されているファイルには効かない
.env を一度でもコミットしていた場合、後から .gitignore に追加してもGitは追跡を続けます。
git rm --cached .env
git commit -m "Remove .env from tracking"
この操作で現在の追跡は止められますが、過去のコミットにはシークレットが残ります。
2. ディスク上のファイルには効かない
.gitignore はGitの挙動を変えるだけです。.env ファイル自体はワークスペースに残ります。悪意のあるVS Code拡張機能はGitインデックスではなくファイルシステムを読み取ります。
つまり、.gitignore はローカルツールに対する防御にはなりません。
3. 簡単にバイパスできる
次のような操作で無視ルールは回避できます。
git add -f .env
エディタのソース管理UIやサブディレクトリの設定によって、意図せず追加される可能性もあります。
過去に .env がコミットされたか確認するには、次のコマンドを使います。
# 現在「無視されている」場合でも、そのファイルを触ったすべてのコミットをリスト表示
git log --all --full-history --oneline -- .env
# 履歴に残っている実際のシークレット値を確認
git log -p --all -- .env | grep -iE "key|secret|token|password"
何か見つかった場合、その認証情報は漏洩済みとして扱ってください。対応は次の順序です。
- キーをローテーションする
- 影響範囲を確認する
-
git filter-repoなどで履歴から削除する - チームとリモート履歴の更新を調整する
- 再発防止として、アクティブな認証情報をファイルから移動する
.gitignore は便利です。正直なミスを減らし、差分をきれいに保てます。しかし、防御境界として扱ってはいけません。
被害範囲を縮小する4つの習慣
認証情報が絶対に漏洩しないことは保証できません。しかし、漏洩したキーの価値を小さくすることはできます。
実装すべき習慣は次の4つです。
- スコープする
- 分離する
- 短命にする
- ローテーションする
1. シークレットを環境にスコープする
同じAPIキーを開発、ステージング、本番で使い回さないでください。1つのキーが漏洩すると、すべての環境が同時に危険になります。
環境ごとに別の認証情報を使います。
| 環境 | 使うべきキー | アクセス範囲 |
|---|---|---|
| ローカル開発 | 開発キー | サンドボックス、テストデータ |
| ステージング | ステージングキー | ステージング環境のみ |
| 本番 | 本番キー | 本番ランタイムのみ |
開発キーが漏洩しても、攻撃者が到達できるのはテストデータだけにするのが目標です。
2. 環境を分離する
環境分離とは、単にキーの値を分けることではありません。環境同士が到達できない構成にすることです。
たとえば、次のようにします。
- 開発DBは本番DBのリードレプリカにしない
- ステージングの決済プロバイダーはテストモードを使う
- 開発用設定から本番データに接続できないようにする
- 本番キーをローカルマシンにコピーしない
「このキーはどの環境のものか?」に明確に答えられる状態を作ってください。その答えが、漏洩時の深刻度を決めます。
3. 最小権限・短命のキーを使う
盗まれたキーの危険度は、主に2つで決まります。
権限
キーには、そのタスクに必要な最小権限だけを与えます。
たとえば、公開製品カタログを読み取るだけのフロントエンドビルドに必要なのは、読み取り専用キーです。書き込み権限、請求権限、管理者権限は不要です。
多くのAPIプロバイダーは、スコープ付きキーや細粒度トークンをサポートしています。GitHubの細粒度パーソナルアクセストークンは良い例です。
トークン方式を検討する場合は、APIキーとOAuthの比較記事も参考になります。短命なOAuthトークンが静的キーより適しているケースがあります。
寿命
1時間で期限切れになるキーは、攻撃者にとって価値が低くなります。盗まれたデータセットが売買され、攻撃者がキーを試す頃には無効になっている可能性が高いからです。
一方、無期限の静的キーは危険です。誰かが気づくまで機能し続けます。
実装方針は次の通りです。
- 可能ならオンデマンド発行の短命トークンを使う
- 静的キーが必要な場合でも有効期限を設定する
- 高権限キーほど寿命を短くする
- 本番キーを長期間放置しない
4. パニック時ではなく、スケジュールでローテーションする
ローテーションとは、古い認証情報が使えなくなるようにキーの値を変更することです。
多くのチームは、漏洩後に慌ててローテーションします。しかし、そのタイミングで手順が未整備だと、復旧が遅れます。
事前にスケジュール化してください。
例:
| 認証情報 | ローテーション頻度 |
|---|---|
| 高権限の本番キー | 毎月 |
| 通常の本番キー | 1〜3か月ごと |
| ステージングキー | 四半期ごと |
| 開発キー | 四半期ごと、または退職・端末紛失時 |
定期ローテーションには2つの効果があります。
- 未検出の漏洩があっても有効期間を短くできる
- ローテーション手順が日常作業になり、インシデント時に慌てない
関連ツールについては、APIキー管理ツールのまとめも参考になります。
認証情報をワークスペースに散乱させず、Apidogの環境変数に保持する
正直に言うと、ApidogもVS Code拡張機能とMCPサーバーを提供しています。ここで主張したいのは、「特定のクライアントツールはサプライチェーン攻撃に免疫がある」ということではありません。クライアント側ツールに絶対の免疫はありません。
重要なのは、シークレットがどこに存在するかです。
API開発では、次のような値を頻繁に扱います。
- Bearerトークン
- APIキー
- データベース接続文字列
- JWT署名用シークレット
- サードパーティAPIの認証情報
デフォルトの行動は、これらを .env やテストスクリプトに置くことです。しかし、それではアクティブな認証情報がワークスペース内のプレーンテキストファイルに残ります。これは、悪意のある拡張機能が探す対象そのものです。
Apidogの環境システムを使うと、これらの値をリクエスト定義から分離できます。
プレーンテキストファイルではなく環境変数を使う
Apidogでは、認証情報をリポジトリ内のテキストではなく、環境変数として保存できます。
リクエストでは、実値ではなく変数名を参照します。
Authorization: Bearer {{access_token}}
避けるべき例は次のような形です。
Authorization: Bearer sk-proj-aB3dEf9hKlMnOpQrStUvWxYz1234567890
変数を使えば、リクエスト定義に実際のシークレットを書かずに済みます。送信時にApidogが値を解決します。
この構成により、認証情報はソースコードや .env の隣にあるプレーンテキスト行ではなく、APIクライアント内の管理された値として扱われます。
ローカル値でシークレットをマシンに留める
Apidogでは、変数に対して共有値とローカル値を分けられます。
- 共有値または初期値: チームに共有される値
- ローカル値または現在値: 自分のマシンに残る値
トークンやパスワードなどの機密データは、ローカル値に入れるべきです。これにより、プロジェクト構造を共有しても、実際のシークレットは同期されません。
チームメイトが取得するのは、たとえば次のような変数名と構造です。
access_token
db_password
payment_api_key
しかし、あなたの実際の値は共有されません。各開発者が自分のローカル値を入力します。
この設計により、次のリスクを減らせます。
- 実キー入りの
.envを共有する - 本番トークンをAPIリクエスト定義に保存する
- チーム全員に同じ認証情報を配る
- リポジトリや同期データに実シークレットが混入する
環境管理で開発・ステージング・本番を分ける
Apidogの環境管理では、開発、ステージング、本番などの環境を定義できます。それぞれに異なるベースURLと変数値を設定できます。
例:
| 変数 | 開発 | ステージング | 本番 |
|---|---|---|---|
base_url |
https://dev-api.example.com |
https://stg-api.example.com |
https://api.example.com |
payment_api_key |
サンドボックスキー | テストモードキー | 本番キー |
access_token |
開発用トークン | ステージング用トークン | 本番用トークン |
リクエスト側は同じままです。
GET {{base_url}}/orders
Authorization: Bearer {{access_token}}
環境を切り替えると、参照される値のセットが切り替わります。リクエストを編集して本番キーを貼り直す必要はありません。
これにより、次のような運用がしやすくなります。
- 開発環境ではサンドボックスキーだけを使う
- 本番キーをローカル開発に持ち込まない
- 環境ごとの認証情報を明確に分離する
- 誤って開発キーで本番APIを叩くリスクを減らす
厳密な境界線が必要なチーム向け: Vaultシークレット
本番シークレットをAPIクライアントに直接保存したくないチームでは、Apidog EnterpriseプランのVaultシークレット機能を利用できます。
Vaultシークレットは、次のような専用シークレットマネージャーから値を取得します。
- HashiCorp Vault
- Azure Key Vault
- AWS Secrets Manager
ApidogはVaultのパスやメタデータのみを保存します。実際のシークレット値はオンデマンドで取得され、プロジェクト経由でチームメイトに共有されません。
本番認証情報の保管場所を、専用のシークレットマネージャーに維持できるのがポイントです。
Apidogで実装する手順
API認証情報を .env からApidogの環境変数へ移すには、次の流れで進めます。
- Apidogをダウンロードする
- プロジェクトを作成する
- 環境管理を開く
-
development、staging、productionなどの環境を作成する -
access_tokenやpayment_api_keyなどの変数を追加する - 機密値はローカル値として入力する
- リクエストでは
{{access_token}}のように参照する -
.envやスクリプトから実キーを削除する - 過去にコミット済みならキーをローテーションする
注意点として、シークレットをApidogに移すことで、リポジトリやワークスペース内のプレーンテキスト認証情報は減らせます。しかし、マシン自体が侵害されたツールに対して無敵になるわけではありません。
引き続き、次の対策は必要です。
- インストールする拡張機能を監査する
- 不要な拡張機能を削除する
- 本番キーを最小権限にする
- 短命な認証情報を使う
- スケジュールに従ってローテーションする
Apidogは「認証情報をどこに置くか」の問題を改善します。端末全体の防御は、引き続き多層防御で考える必要があります。
結論
GitHubの侵害が示したのは、攻撃者が開発者マシンを狙っているという現実です。信頼されたエディタ、便利な拡張機能、プレーンテキストの設定ファイルがそろった環境は、本番サーバーよりも柔らかい標的になり得ます。
今すぐできる監査は次の通りです。
# よくあるシークレット名を検索
grep -RniE "key|secret|token|password" .
# .env が履歴にあるか確認
git log --all --full-history --oneline -- .env
# 履歴内のシークレットらしき値を確認
git log -p --all -- .env | grep -iE "key|secret|token|password"
何か見つかった場合は、漏洩済みとして扱います。
- 該当キーをローテーションする
- 影響範囲を確認する
- Git履歴から削除する
- アクティブな値をプレーンテキストファイルから移す
- 今後は環境変数、ローカル値、Vault連携を使う
次のAPI認証情報から、.env やスクリプトに実キーを置くのをやめてください。Apidogをダウンロードし、環境変数として管理するだけでも、ワークスペース内に露出するシークレットを減らせます。
より広い文脈については、GitHub侵害後のセルフホスト型APIツールとAPIキー管理ツールも参考になります。
よくある質問
VS Code拡張機能は本当に .env ファイルやAPIキーを読み取れますか?
はい。VS Code拡張機能は、ユーザーアカウントのファイル権限でエディタプロセス内で実行されます。ディレクトリの一覧表示、ファイルのオープン、.env、設定ファイル、~/.aws/credentials などの読み取りが可能です。
これは多くの場合、通常の拡張機能動作です。問題は、悪意のある、または侵害された拡張機能が同じアクセス権を使ってシークレットを収集できることです。
.gitignore に .env を追加するだけでAPIキーを保護できますか?
いいえ。.gitignore は、未追跡ファイルを git add から除外するだけです。
次のものは保護できません。
- すでにGitで追跡されている
.env - Git履歴に残ったシークレット
- ディスク上に存在する
.env - ローカルツールや拡張機能による読み取り
.gitignore はミスを減らすための衛生対策であり、セキュリティ境界ではありません。
Git履歴にAPIキーを見つけた場合、どうすべきですか?
リポジトリがプライベートでも、直ちに侵害済みとして扱ってください。
対応手順は次の通りです。
- キーをローテーションする
- 該当キーの利用ログを確認する
-
git filter-repoなどで履歴から削除する - チームと調整してクリーンな履歴を反映する
- アクティブな認証情報をプレーンテキストファイルから移す
継続的な運用については、APIキー管理ツールも参考になります。
ApidogにAPIキーを保存すると、露出はどのように減りますか?
Apidogでは、認証情報を環境変数として保存し、リクエスト内では名前で参照できます。
Authorization: Bearer {{access_token}}
これにより、実際のシークレットをリポジトリ内の .env やスクリプトに直接置く必要が減ります。また、ローカル専用値を使えば、トークンやパスワードをサーバーやチームメイトに同期せず、自分のマシンに留められます。
ただし、これは端末が侵害された場合の完全な防御ではありません。拡張機能の監査、最小権限、短命キー、ローテーションは引き続き必要です。
ApidogもVS Code拡張機能を持っていますが、それはリスクですか?
はい、ApidogはVS Code拡張機能とMCPサーバーを提供しています。この記事の要点は、特定のクライアントツールがサプライチェーン攻撃に免疫を持つということではありません。
重要なのは、シークレットがどこに存在するかです。認証情報をローカル専用値やVault連携に置くことで、ワークスペース内のプレーンテキストキーを減らせます。これは、マシン上のどのツールが侵害された場合でも、スクレイピング対象を減らすための対策です。
APIキーのスコープ設定とローテーションの違いは何ですか?
スコープ設定は、キーができることを制限します。
例:
- 開発キーはサンドボックスのみ
- 読み取り専用キーは書き込み不可
- 決済キーは決済APIだけに限定
ローテーションは、古いキーを無効化し、新しい値へ切り替えることです。
スコープ設定は漏洩時の被害を小さくします。ローテーションは漏洩キーが使える期間を短くします。両方が必要です。
APIキーはどのくらいの頻度でローテーションすべきですか?
インシデント後だけでなく、固定スケジュールでローテーションしてください。
目安は次の通りです。
- 高権限の本番キー: 毎月
- 通常の本番キー: 1〜3か月ごと
- ステージングキー: 四半期ごと
- 開発キー: 四半期ごと、または端末紛失・退職時
チームのリスク許容度やコンプライアンス要件に合わせて調整してください。
本番APIキーは開発者のノートパソコンに置くべきですか?
理想的には、置くべきではありません。本番認証情報は、可能な限り少ない場所に存在すべきです。通常は、専用のシークレットマネージャーと本番ランタイムに限定します。
開発者は、非本番データにスコープされた開発用またはステージング用の認証情報で作業すべきです。ノートパソコンが侵害されても、攻撃者が到達できるのはサンドボックスに限定される状態を目指してください。
Top comments (0)