12
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

開発者ツールでテストしたら本番環境だった話 〜不正入力とバリデーションの大事さ〜

Last updated at Posted at 2025-12-13

この記事は 本番環境などでやらかしちゃった人 Advent Calendar 2025 14 日目の記事です。
https://qiita.com/advent-calendar/2025/yarakashi

※この記事は、とある社内Webアプリで実際にやらかしかけた出来事を、身バレしない程度に脚色したものです。

前提:社内向けWebアプリと役割分担

とある社内Webアプリの開発をしていました。
目的は、工場のデータを集計・可視化し、不具合調査などで担当者があちこちのシステムを横断する工数を減らすことです。

役割分担はこんな感じでした。

  • 私:フロントエンド担当(新卒)
  • 同期:サーバーサイド担当(同じく新卒)
  • それぞれに先輩が1人ずつついていて、合計4人体制

コードベースとしては、フロントもサーバーサイドも「読もうと思えば一応読める」状態でしたが、基本は自分の担当に集中という形でした。

リリース直前、PMからの一言

テスト環境へのマージも終わり、基本的なテストも一通り完了したタイミングで、PMからこんなひと言が飛んできました。

「2日後にリリース予定だから、時間ある人はランダムテストでもしておこうか」

私「かしこまりました!」

ということで、私はフロント担当として、

  • 旧UIと新UIを並べて差分を確認
  • 想定どおりの画面遷移か
  • レイアウト崩れや表示崩れがないか

などを、ブラウザを2つ開いて黙々とチェックしていました。

「これ、編集モードで数字書き換えたらどうなるんだろ?」

UIには、一覧の表示件数を切り替えるドロップダウンがありました。

  • 5件
  • 10件
  • 20件
  • 50件

といった選択肢があり、選ばれた件数をクエリパラメータとして API に送り、その件数分のデータを取得する実装です。

ここで、好奇心旺盛な新人エンジニアであった私は、ふとこう思ってしまいます。

「編集者モードで内部の数字を変えてリクエスト投げたらどうなるんだろ」

  • ドロップダウンの選択肢はUI側で制御しているだけ
  • 入力値自体のバリデーションはフロントではしていない

つまり、開発者ツールで値をいじれば、そのまま好きな数字をサーバーに飛ばせてしまう状況でした。
サーバーサイドで対策していなければ送った数字をそのまま鵜呑みに処理してしまいます。

そして私は、なぜかその実験を「本番環境のUI」でやってしまいました。
テスト環境ブラウザと間違えちゃったんです。

実際にやってみた結果

ブラウザの開発者ツールを開き、表示件数の値を書き換えてみます。

  • 本来:5 / 10 / 20 / 50
  • 私:100 を直書き

そのままリクエストを送信すると──

  • 本当に100件分のデータが返ってきた
  • つまりサーバー側では、特に制限もバリデーションもされていない

「あー、これは普通にダメなやつだ」と悟り、その場で先輩に即報告しました。

  • テスト項目に「不正入力」を細かく追加
  • サーバー側:上限値・許可リストを使ったチェックを実装
  • フロント側:UIから送れる値も改めて制御

と、その場で修正対応になりました。

この時点ではまだ、自分がやらかした場所が「本番環境」だという自覚が薄いままでした。

バレたきっかけ

しばらくして、サーバー側の先輩がログを確認していて、ふと違和感を覚えます。

「テスト環境のログに、100件取得のリクエストが一度もないな……?」

そこで、念のため本番環境のログを確認。

「……本番でテストしてるやん」

先輩の発言は完全な想像ですが、私が本番環境で「100件」のテストをしていたことが発覚しました。

幸い、入力した値は 100 と、そこまで非常識な件数ではなかったため、負荷的には特に大きな問題にはなりませんでした。

ただ、先輩からはこう言われました。

「これ、もし 9999999999 とか投げてたら、本番で503祭りになってたかもしれないからね」

はい、その通りです。完全に反省しました。

もし悪意あるユーザーだったら?

今回のケースは、たまたま私が本番で遊んでしまっただけでしたが、もしこれが外部向けサービスだったら、想像できる被害はもっとシャレになりません。

例えば:

  • とんでもない件数を指定して高負荷をかける
    • 意図せず DDoS っぽい状態になり、503エラーでサービス停止
  • SQLを書き込めるような実装になっていたら(なっていてはいけないが)
    • DROP TABLE users; のようなクエリを送られ、ユーザー情報が吹き飛ぶ
  • ビジネスロジック用のパラメータを直接いじられて、不正な操作や情報取得ができてしまう

など、インシデントとしては普通に「重大事故」クラスになりえます。

「UIで選べる値だから大丈夫でしょ」は、フロントエンド開発者の幻想であり、サーバー側としては一切信用してはいけない、ということを身をもって学びました。

技術リーダーの反応と、その後

この話を先輩に報告したところ、

  • 「この失敗、めちゃくちゃ勉強になるから新人向けに共有して」
  • 「資料にして発表してみたら?」

と言われ、同期と一緒に社内向けの発表資料を作りました。

結果として、

  • 技術リーダー → 私たち:「よく気づいたし、ちゃんと共有してくれてえらい」とむしろ評価
  • 技術リーダー → サーバーサイドをレビューした先輩:「UI前提にしてたのはよくなかったね」と少し強めに注意される(本当にすみません)

という、着地となりました。

学んだことまとめ

今回の件で、私が学んだことを整理するとこんな感じです。

  • 本番環境でテストするのは、基本的にアウト
    • たとえ「ちょっとした確認」のつもりでもダメ
  • ミスをしない方法の構築大切
    • 対した工夫じゃないですが、これ以降テスト環境をシークレットモードで開くようにしました
  • サーバーサイドは、UIを絶対に信用しない
    • 表示件数・ページ番号・ID・フラグなど、外から来る値は必ずバリデーション
    • 「どうせUIからしか触れないから」は、攻撃者にも開発者にも通用しない
  • 社内アプリだからといって油断しない
    • 今回は「社内 only」「入力値がまだ常識の範囲内」という幸運が重なっただけ
  • 「やらかし」を隠さず共有する文化は大事
    • 失敗談を共有することで、同じ事故を未然に防げる
    • 本人も周りも学びになる

この記事が、どこかの新人エンジニアの役にたったら幸いです。
まあ私もまだ3年目エンジニアなので精進あるのみの身ですが......
皆さまも、お気をつけてください。来年もよろしくお願いいたします。

12
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?