この記事は、自社が運営するAI製品で見つかったセキュリティ上の不備と、その修正を記録するシリーズの1本である。子ども向けAI英語教材「Puku」のログインAPIが、送信したはずのワンタイム認証コードを応答のJSONにそのまま含めて返していた問題と、2026年9月の修正内容をまとめる。
この記事で分かること
- サーバー応答に何が混入していたか
- ログイン画面が無い間、なぜこの問題に気づけなかったか
- 2026年9月にどう直し、どこまで実機で確認したか
この記事で分からないこと(正直に書く)
- この応答が本番で実際に第三者に読まれ、悪用されていたかどうか(一次資料にはアクセスの有無までの記載がない)
何を作っていたか
Pukuは保護者のメールアドレスへワンタイムの認証コード(OTP)を送り、それを入力してログインする方式を採用している。2026年9月、それまで配線していなかったログイン画面のUIを本番に接続して公開した(出所: 自社の運用記録、確認日2026-09-06)。
どこに穴があったか
ログイン開始のエンドポイントは、登録済みメールへのコード送信に成功すると、6桁のコードそのものを応答のJSONに含めて返していた。実装には「メール配信は未実装、当面は応答に直接コードを出す」という趣旨のメモが残っており、それが本番にそのまま乗っていた。加えて、メールアドレスが未登録の場合は登録の有無が分かる別の応答を返しており、メールアドレスを知っているだけで登録済みかどうかも外部から判別できた(出所: 自社の運用記録、確認日2026-09-06)。第三者がメールアドレスを知っていれば、その保護者としてログインし、子どもの学習データに触れられる状態でもあった。ログイン画面が無い間はこの応答を見るクライアントが存在せず表面化しなかったが、UIを配線したことで入口が実質的に公開された。
どう直したか(2026年9月)
最初に取った処置は、問題のログインUIを含まない直前バージョンへ一旦戻す、可逆なロールバックだった。そのうえでサーバー側を修正し、応答からコードのフィールドを削除して実際のメール配信サービス経由で送るよう切り替え、登録済みかどうかにかかわらず同じ形の応答を返すようにし、短時間の連続リクエストにも間隔を設けた。修正はステージング環境で、登録・コード送信(配信サービス側のイベントで到達を確認)・誤ったコードを複数回試す、という一連の流れを実機で確認し、本番の更新内容が変更と一致していることを確かめてから公開した(出所: 自社の運用記録、確認日2026-09-06)。
OWASPの「Forgot Password Cheat Sheet」は、アカウントの有無にかかわらず一貫した応答を返し、応答時間も揃えるべきだとしている。今回の修正はこの方向と一致する(出所: OWASP Cheat Sheet Series「Forgot Password Cheat Sheet」https://cheatsheetseries.owasp.org/cheatsheets/Forgot_Password_Cheat_Sheet.html、確認日2026-09-06)。
同じ穴を持つ製品の見分け方
認証コードやパスワード再発行を扱うAPIを、開発者ツールやcurlのようなツールで実際に叩き、レスポンス本体を見るのが最も早い確認方法である。JSONの中に開発用らしき名前のフィールドが残っていないか、コードそのものが入っていないかを見る。あわせて、登録済みメールと未登録メールとで応答の文言・構造・返ってくる速さが変わらないかも確認したい。変われば、それだけで登録者かどうかの手がかりを外部に与えていることになる。
試行回数の制限まで踏み込んだ内容は認証コードの試行回数を制限した記事、公開範囲を絞る設計はレート制限を敷いた記事、監査ログの残し方は社内文書RAGの監査ログ設計の記事を参照してほしい。
自社製品の認証まわりの設計や監査について相談したい場合は、お問い合わせから編集部まで連絡してほしい。
よくある質問
Q1. サーバーの応答には具体的に何が含まれていたのか
コード送信に成功した際の応答JSONに、6桁の認証コードそのものが含まれていた。メールが未登録の場合は別の応答が返り、登録の有無も外部から判別できた。
Q2. なぜログイン画面が無い間、問題に気づけなかったのか
ログインUIが本番に配線されておらず、応答を実際に見るクライアントが存在しなかったため、問題として認識されていなかった。UIを配線したことで、応答本体を見ればコードが読める入口が表になった。
Q3. 修正はどのように確認したのか
ステージング環境で、登録・コード送信・配信サービス側でのイベント確認・誤ったコードを複数回試す動作までを一連の流れとして実機で確認し、本番の更新内容が意図した変更と一致していることを確かめてから公開した。
Q4. 修正後、未登録メールへの応答はどう変わったのか
登録済みメールと未登録メールのどちらに対しても、同じ形の応答を返すようにした。これにより、応答の違いから登録の有無を推測できない状態にした。