声で話すAIペット「コハク」を5つの役に監査させたら、鍵が「未設定なら素通し」だった
音声AIの入口の鍵が、設定を忘れた瞬間に全部開く作りでした。見つけたのは作った本人ではなく、役を分けて読ませた監査です。
コハクは、スマホの中に住む小さな相棒AIです。声で話しかけると返事をして、カメラに映ったものにも反応します。2026年6月に作って、いまも kohaku.nextcode.ltd で動いています。

作ったあとに、自分で「壊れるところ」を探す日を1日取りました。2026-06-14 の 12:13 からです。結果を先に書くと、見つかったのは重大5件・中11件・軽微13件の計29件。33分後の 12:46 には、重大と中の16件のうち15件が直っていて、残る1件は一部だけ対応した状態でした。
15つの役に、別々の角度で読ませた
読ませたのは5役です。実行時のバグを探す役、画面と使い心地を見る役、設計と保守を見る役、壊れ方(異常系)を試す役、そして全部をまとめる統合役。同じ原因から出た指摘が何本も上がってくるので、統合役が「根本原因」ごとに1件へ束ねました。
自分で読むと、どうしても「動いたところ」を見てしまいます。役を分けると、見る場所が散らばる。それだけで、僕が見ていなかった穴が出てきました。
2いちばん危なかったのは、「合言葉が未設定なら素通し」
コハクは、合言葉を入れた人だけが使えます。声の会話は OpenAI の音声APIにつながっていて、使われた分だけ料金がかかるので、入口の鍵はお金に直結します。
ところが認証のコードは、合言葉の設定が空なら無条件で通す作りでした。ローカルで試すときに楽なので、最初にそう書いてあったんです。この「素通し」は本番にもそのまま効きます。環境変数を入れ忘れてデプロイすると、音声の料金がかかるトークン発行の窓口と、全員の会話・顔の記録・画像を見られる管理用の窓口が、どちらも誰にでも開く。
正直に言うと、本番が実際に開いていたことがあったのかは分かりません。デプロイのときは合言葉を設定していました。ただ、設定を忘れたら開く作りのまま動かしていたことは、確かです。
直しは 12:27 の1コミット。本番(Vercel か production)で合言葉が未設定なら通さない。素通しはローカル開発だけにする。合言葉の比較も、返事の速さの差で1文字ずつ当てられないよう、固定時間で比べる関数に替えました。
直したあとの本番を、今日(2026-10-15)あらためて確かめています。合言葉なしでトークン発行の窓口を呼ぶと、HTTP 401 が返ってきました。
3「読めなかった」を「無かった」と読んでいた
もう1つ痛かったのが、育成データの扱いです。コハクにはごはん・なつき度・レベルがあって、Supabase に保存しています。読み込みのとき、通信が一瞬こけて「エラーの返事」が来ると、コードはそれを「保存データがまだ無い人」と読んで、初期値を上書き保存していました。
つまり、通信が1回失敗しただけで、育てたレベルが1に戻って、そのまま消える。直しは単純で、読み込みに成功したと確かめられたときだけ「無い」と判断する。読めなかったときは何も書かず、手元の値を残します。
4マイクが付いたまま、料金も回り続ける
三つめは、音声の接続を途中でやめたときの後始末です。「起こす」を押した直後に画面を離れたり、接続の交換が失敗したりすると、マイク・通信・タイマーが解放されずに残っていました。マイクのランプが点いたまま、音声APIの料金も進んでしまう。
後始末を1か所にまとめました。どの道で終わっても必ずその関数を通り、途中だった通信は中断される。画面側にも片付けの処理を足して、二重にしています。
重大5件の中身と、直し方(2026-06-14)
| 症状 | 原因 | 直し方 |
|---|---|---|
| 音声セッションが残る(マイク点灯・課金が続く) | 失敗時に解放する処理が無い | ◎終了を1か所に集約・通信を中断可能に |
| 育成データが初期化される | 読み取り失敗を「データ無し」と判断 | ◎成功を確認できたときだけ新規作成 |
| 合言葉が未設定だと全開放 | 未設定なら通す条件 | ◎本番は未設定なら拒否・固定時間の比較 |
| 記憶をワンタップで消せる | 確認も取り消しも無い | ◎2回押しで削除・失敗したら元に戻す |
| マイクを拒否すると行き止まり | 「接続に失敗」としか出ない | ◎拒否と未接続を見分けて、直し方を文で出す |
5監査の指摘が、間違っていたもの
ぜんぶ鵜呑みにはしませんでした。音量メータに微小なずれが出るという指摘は、調べると誤検知でした。波形を読む関数が毎フレーム全域を書き換えるので、ずれは残りません。「外のモードに寝るボタンが無い」も、画面上部の月のボタンで終われるので、行き止まりではなかった。
軽微13件のうち、実際に直したのは3件、誤検知は1件、残り9件は未対応か、一部の対応のままです。
6直さなかったこと
直さなかったものにも、理由を残しました。
1つめは回数制限です。課金の窓口に1分あたりの上限を付けたいのですが、サーバーレスだとメモリ上の数え方は効きません。外部のデータベース(Upstash など)が要るので、インフラを足す判断が先になります。2つめは、1,146行あった画面のファイルの分割。今は1,275行まで伸びています。直すと回帰が怖くて手を付けていません。3つめは、共有の合言葉1つに全データの権限が乗っている認可の作り。これは設計から変える話で、バグ修正と混ぜませんでした。
7まだ分からないこと
この監査は、コードを読んで見つけたものです。声やカメラは実機で触らないと確かめきれません。全部を実機で通したとは言えないんです。回数制限が無い間は、合言葉が漏れたときの料金の上限も、決まっていないままです。
この記事を書いた人
NextCode(沖縄県宜野湾市)は、iOSアプリ・ホームページ/LP・NFCデジタル名刺・AI業務自動化を作っている開発スタジオです。ここで書いているのは、実際に作って公開したものと、その過程で詰まったことだけです。
お問い合わせフォームは24時間受け付けています。