← コラム一覧

【検証実話】生成AIに「入力チェック」と頼んだら、フロントにしか実装されなかった話

生成AIが作った画面を検証していると、「表側は完璧なのに」と感じる瞬間がある。

今回の事例は、顧客登録フォームだった。氏名、メールアドレス、電話番号、住所。どのシステムにもある、ごく普通の登録画面である。生成AIに「入力チェックをつけてください」と頼んで実装されたものだ。

画面のチェックは、正直よくできていた。必須項目を空にすれば赤字が出る。メールの形式が崩れていれば、その場で教えてくれる。電話番号にひらがなを入れれば弾かれる。エラーメッセージの文言まで丁寧で、「問題なさそうだな」と思った。

でも、少しだけ気になって、開発者ツールのNetworkタブを開いた。フォームが送信しているAPIに、画面を通さず直接リクエストを送ってみたのだ。氏名は空、メールアドレスは「あああ」、電話番号はひらがな。

「あれ?」

201が返ってきた。登録成功である。データベースを見ると、名前のないお客様が、メールアドレス「あああ」で登録されていた。画面からは絶対に作れないはずのデータが、裏口からは素通しだった。

画面のチェックが完璧でも、APIは何も守っていないことがある

フロント側の入力チェックは、ブラウザの中のJavaScriptで動いている。つまり、画面を経由しない相手には一切働かない。

APIを直接叩かれる。開発者ツールでリクエストを書き換えられる。別システムからデータ連携される。スマホアプリが後から追加される。経路はいくらでもあって、そのどれもが入力チェックの外側を通る。

フロントのチェックは、正しく入力してくれる人への「案内」でしかない。データを守る「防御」は、サーバー側にしか置けない。この2つは似ているようで、役割がまったく違う。

AIは「入力チェック」を、画面の仕事だと解釈した

なぜこうなったのか。指示が「入力チェックをつけてください」だけだったからだ。

フロントにチェックを実装すれば、この指示は満たされる。画面で試せば完璧に動いて見える。デモも通る。AIは間違えたわけではなく、一番素直な解釈を選んだだけだった。

以前書いた、「削除」と頼んだら物理削除で実装されていた話と、まったく同じ構造である。「削除」という言葉に物理か論理かの区別があるように、「入力チェック」という言葉にも、フロントかサーバーかどちらもか、という区別がある。言葉を雑に渡すと、AIは雑に受け取ったなりに、きれいなものを作ってしまう。

画面から試すだけでは、この穴は一生見つからない

怖いのはここだ。テストケースが「画面から不正な値を入力するとエラーになること」だけなら、この実装は全項目合格する。

必須チェック、合格。形式チェック、合格。桁数チェック、合格。試験成績書はきれいに埋まって、リリース判定も通る。それでもAPIはノーガードのままだ。

私が気付けたのは、守りが1枚に見えたとき、その1枚がどこにあるかを確認する癖があったからだと思う。フロントのチェックとサーバーのチェックは、2枚で1セット。画面で弾かれたときこそ、「では画面を通らなかったら?」と裏に回る。QAの仕事は、正面玄関の確認だけではない。

「入力チェックして」は、どこで守るかまで言わないと伝わらない

それ以来、AIに入力チェックを頼むときは、ここまで書くようにしている。

「入力チェックはフロントとAPIの両方に実装してください」
「APIは不正な値を400エラーで返してください」
「フロントのチェックは利用者への案内、サーバー側のチェックを最終防衛にしてください」

ここまで書いて、ようやく両側にチェックが入る。逆に言えば、この一言を足すだけで防げた穴だった。AIが悪いのではなく、「入力チェック」という言葉に込めていたつもりの意味を、こちらが言葉にしていなかったのだと思う。

まとめ

画面がきれいに弾いてくれるほど、裏側は確認されなくなる。完璧なフォームは、完璧な守りに見えてしまうからだ。

あなたのシステムのフォームの裏側で、APIは誰が守っているだろうか。

関連記事