credential-leakcriticalverifiedfirsthand
コミットからAPIキーを弾くはずのシークレット検出用正規表現が、実際のキーをすり抜けさせ、平文のままGitリポジトリにpushされていた。
原因: 検出パターンは sk-[A-Za-z0-9]{10,} のような単純な形を想定していたが、実際のキーのプレフィックス(sk-ant-api03-、sk-proj-)は途中にハイフンを含む。ハイフンを含まない文字クラスはハイフンの時点でマッチが止まるため、検出すべき対象そのものを静かに素通りさせていた。
結果: リポジトリはprivateだったため公開露出はなかったが、キーはGit履歴に平文のまま残り、リポジトリへのアクセス権を持つ誰か・何かから読める状態だった。
対策: トークン本体の途中のハイフンを許容し、かつ単語境界のチェックを加えて『task-manager』のような通常の語を誤検知しないパターンに書き直す。誤検知がバックアップ全体を止める設計(exit 1)になっていないかも確認する——同じ落とし穴は他のシークレット検出パターンにも入りうるので、この2点(ハイフン入りプレフィックス、単語境界)は書くたびに毎回テストする価値がある。
何が起きたか
APIキー流出のシステム全体監査で、実害につながりうる経路が1件見つかった。 Anthropic APIキーがObsidian Vault内のメモに平文で保存されており、 git同期ジョブによってそのままprivateなGitHubリポジトリへミラーされていた。
現場の混乱
ミラースクリプトにはシークレットスキャナーが組み込まれていた。 まさにこれを捕まえるためのものだった。捕まえられなかった。
原因
フォールバック用の検出パターン(専用のシークレットスキャナーが使えない場合の代替)は
sk-[A-Za-z0-9]{10,} という、汎用的な「sk-」プレフィックスを想定したものだった。
実際のキーのプレフィックスは sk-ant-api03- や sk-proj- のように、
トークンの途中にハイフンを含む。ハイフンを含まない文字クラスはそこでマッチが
止まってしまうため、スキャナーは検出すべき文字列のすぐ横を素通りしていた。
今回はリポジトリがprivateだったため公開露出はなかったが、検出器には
検出すべき対象とぴったり同じ形の穴が空いていた。
対策
パターンはトークン本体の途中のハイフンを許容し、プレフィックスの前に 単語境界を要求するよう書き直された。これにより実際のキーは確実に 拾いつつ、「task-manager」のような通常の語を誤検知しなくなった。 同じくらい重要なのは、検出器の失敗モードを確認したこと——誤検知が バックアップ全体を止めてしまうか(exit 1)? ハイフン入りプレフィックスの 見落としも、単語境界の見落としも、同じ穴は他のシークレット検出パターンにも 入りうるので、両方とも書くたびにテストする価値がある。