Devin観察日記 8日目
今日は実際に発生したヒヤリハットを紹介します。なんと、Devinが秘密鍵の一部をコードに含めてGitHubにpushしてしまったのです。
幸い、情報漏洩にはならずに済みましたが、この一件は多くの学びがありました。
注:この記事では、GCPのサービスアカウントのJSONキーに入っている private_key のことを便宜上「秘密鍵」と呼んでいます。正式名称がわからないので…
この話の前提
運用中のWebサービスで、インフラはFirebaseを全面的に採用しています。開発環境(dev)と本番環境(prod)でプロジェクトを分けて管理しており、Devinには、開発用のサービスアカウントのキーを「Secrets」機能を通じて渡していました。Firebaseのローカル開発サーバを起動するだけでもCLIの認証が必要という、ちょっと面倒な仕様のせいです。
ちなみにFirebase CLIで認証するのも一苦労でした。気になる方はどうぞ。
発生した出来事
昨日の出来事です。Cloudflare WorkersからFirestoreにアクセスするコードをDevinに書いてもらったところ、特段目を引く箇所がありました。
慌てて確認すると、Devinも慌てた様子で「至急チェックさせていだきます」と返答してきました。心なしか、いつも以上に即レスでした。
そのままの勢いで、模擬値に置き換えてくれたそうです。
行動が早いのは良いですが、GitHubにpushしたら簡単には消せません。Devinはすごくアホな行動をとることがあるのですが、この時がまさにそうでした。
原因の特定
冷静になって該当のコミットを見直してみると、少なくとも完全な秘密鍵ではないようです。最後が … で終わっていますし、何より短すぎる。
結論としては、これは本物の秘密鍵ではありませんでした。しかし、全くのダミーでも、Devinが新たにツールで生成した鍵でもなく、「本物に極めて近い秘密鍵の一部」であることがわかりました。
ここからは僕の推測になります。
Devinはおそらく、本物の秘密鍵を見ながら、この文字列を生成したものと思われます。なぜそんな事をしたのかと言うと、 "hogehoge" とかだと認証ライブラリの validator で弾かれてしまうので、どうにかして文法上 valid な文字列を手に入れたかったのだと思います。
その証拠に(なるのかは分かりませんが)、 Devin はこの部分を何度も書き直していました。少し長くしたり、一部を変えたりといった試行錯誤をしながら、テストが通るか試していたのです。
得られた教訓
この一件から得られた教訓は「Devinに渡した鍵は漏れる」ということです。
Devinには「Secrets」という仕組みがあります。まるで CI の「Secrets」のようで、安全そうに見えます。
ところが、安全なのは Devin に渡す前の話であって、渡した後どうなるかはすべて Devin の振る舞い次第です。
ここで敢えて人間のプログラマーに喩えましょう(LLMを人間に喩えて語るなという批判は一旦脇におきます)。1Passwordを使って安全にキーを渡したところで、人間がうっかり漏らすリスクを完全になくすことは不可能です。解決策は、「漏れた時のダメージを最小化する」か、「そもそも渡さない」のどちらかしかありません。
さらに、 Devin.ai というサービスの設計にも大きな改善の余地があります。DevinのOrganizationに所属しているメンバーはDevinの開発環境に直接アクセスすることが可能です。さて、ルートディレクトリで ls してみましょう。
想像してみてください。我々はDevinというAIプログラマーのPC画面や過去の操作履歴を常にダッシュボードから監視できてしまうのです。つまり、Devinに渡した鍵は、少なくともチームメンバー全員が見えてしまいます。
この一見クリティカルにも見える課題は、おそらく次のビジネスチャンスになりうるでしょう。なんて適当なことを言って締めたいと思います。(あまり本気にしないで下さい、僕はセキュリティの専門家ではないので…)
後日談というか、今回のオチ
今回の件を受けて、「秘密鍵をテストファイルに書かない」という新しいKnowledgeがDevinに追加されました。Devin自身が考えた「知見」です。
かわいいですね。