世界を動かす技術を、日本語で。

DrawAFish.com ポストモーテム

概要

DrawAFish.comで発生した約6時間のインシデントについての振り返り。 主な被害はユーザー名の悪用と不適切な魚イラストの承認。 原因は過去漏洩済みの管理者パスワードや認証不備、JWTの実装ミス。 復旧は手動対応とコード修正で実施。 「vibe coding」のリスクと学びを赤裸々に語る反省記。

DrawAFish.com インシデント振り返り

  • 発生期間 :2025年8月3日 2時~8時(EST)約6時間
  • 主な被害
    • 全ユーザー名が差別用語等に書き換えられる被害
    • 不快な魚イラストの承認、良質な魚イラストの削除
  • 影響範囲 :DrawAFish.comの全ユーザーアカウントとイラスト投稿

主な原因

  • 過去漏洩済みの6桁管理者パスワード の流用
    • Neopets.com等で漏洩したパスワードをテスト時に使用
    • Google認証導入後も古いパスワードが有効のまま放置
    • ネット上の情報から第三者が管理者権限でログイン可能に
  • ユーザー名変更APIの認証不備
    • バックエンド実装時に認証ロジックを省略
    • 誰でも任意ユーザー名へ変更可能な状態
  • JWTトークンのユーザー紐付けミス
    • JWTによる認証は実装済みだが、トークン発行ユーザーと操作ユーザーの一致確認を怠る
    • 管理者権限の不正利用が可能な状態

復旧対応

  • 被害発覚後の初動対応
    • 7:45amに状況把握し即デスクで対応開始
    • Firebaseバックアップの設定ミスを修正しつつ、認証必須化を即時実施
  • 復旧作業
    • モデレーションログを活用し、被害アクションをスクリプトで巻き戻し
    • 不明なモデレーターアカウント(IceWeasel)を一時的にBAN
    • JWT認証バグの修正
    • IceWeasel氏とDiscordで連絡を取り、コードベースのセキュリティ改善を共同実施
  • 協力者の存在
    • HackerNewsユーザー@iceweaselfan44が不適切な魚イラスト削除等で緊急対応に貢献

反省と学び

  • vibe coding(勢い重視のコーディング)のリスク
    • Copilot等の自動生成コードをレビューせず高速実装
    • テスト・TODO・ドキュメントを省略し、「後で直す」と放置
    • 結果として重大な認証バグ・脆弱性を見逃す
  • 責任の所在
    • LLM(AI)には責任なし、最終的な品質・安全性担保は開発者自身の責任
  • 「仕事ではやらない」ことでも、趣味開発で油断しがち
    • 本業ではコードレビューやドキュメント作成を徹底
    • 趣味開発で手抜きをすると痛い目を見る教訓

メッセージ

  • スピード重視開発の功罪
    • 早く作る楽しさと、セキュリティ対策の重要性
  • LLMやCopilotはあくまでツール
    • レビューと最終判断は人間が行うべき責務
  • 「やらかし」から学ぶことの大切さ
    • 失敗を認め、改善に活かす姿勢

関連リンク・トピック

  • Show HN: Draw a fish and watch it swim with the others
    • https://news.ycombinator.com/item?id=44719222
    • 2025年7月、HackerNewsで注目されたプロジェクト

まとめ

  • 勢いだけの開発 は一時的な楽しさと引き換えに大きなリスクを伴う
  • 認証・認可の実装ミス はサービス全体の信頼性を損なう危険
  • 失敗事例の共有 は開発者コミュニティの学びに繋がる
  • CopilotやLLMの活用 には必ず人間の目によるレビューが必須
  • 「やらかし」もオープンに語り、次に活かす姿勢 の重要性

Hackerたちの意見

私は「ラッキー」な数人の一人で、スラーフィッシュの学校を目撃しました。セキュリティの仕事をしているから、あまりにもひどい状況に笑っちゃったけど、同時にHNで手が空いてる人が助けに来るだろうなって思ってました。このポストモーテムもありがたいです。最近のIRでは、プロダクションでのバイブコーディングが私の仕事の大部分を占めてるけど、こんな低リスクなプロジェクトがちゃんとドキュメント化されてるのを見るのは良かったです。

「バイブコーディングのせいだ」ってすぐに言う人がいるけど、少なくとも二つの問題はAIなしの設計されたシステムでも結構よくあることなんだよね。「テスト管理者」アクセスを残したり、トークンを確認するけどクロスチェックしなかったり。

なんか、ランダムな人がセキュリティホールを使って悪意のある行動に対抗しようとしたのがすごいよね(笑)

これは素晴らしかった。人々は驚くべき存在だね。

これ、私が覚えている限り何度か起こったことがある - 一つは穴をパッチするワーム/エクスプロイトだった。

5年くらい前に、FBIがまさにこれをやってEternalBlueのエクスプロイトに対抗してたって読んだ記憶がある(エクスプロイトの名前が間違ってるかもしれないけど)。

素晴らしいプロジェクトだし、投稿も良かった。文章が上手で面白いね。もっとRSSリーダー用に見たいな :-)

…もしRSSがあれば…

開発者なら、魚の絵をミラーリングするオプションを追加した方がいいと思うよ。左向きの魚は描けるけど、右向きの魚を描くのがなんかすごく難しいんだよね。

左向きに描いてから、横にひっくり返せばいいんじゃない?

認証なしでどの魚でもアップボートできるよ。1分間にIPごとに20票までの制限があるからね。POST https://fishes-be-571679687712.northamerica-northeast1.run.a... {"fishId":"xxxx","vote":"up"}

それは実は意図的なデザインなんだよね。魚をちょっと好きになったり、すごく好きになったりできるから、思いっきりアップボートやダウンボートできるようにしてるんだ :)

すごくいいポストモーテムだね、特に雰囲気重視のアプリだから。レゴハウスの「ビルド・ア・フィッシュ」展示からインスパイアされたのかな?最近行ったけど、自分が作った魚が他の魚と泳ぐのを見るのがめっちゃ中毒性あるよね :) https://www.youtube.com/watch?v=KYs3ne0HCwM

あ!これ見たことなかった。私はセントルイス水族館(色を塗った魚が泳ぐやつ)や、グーグルのクイックドロー(2016年頃の思い出)からもっとインスパイアを受けたよ。

「vibe-coded」の「S」はセキュリティのことだよ。

Sは蛇…じゃなくて、ドラゴンだよ…

JWTを使ってログインを認証したけど、そのJWTトークンが管理者のアクションに関連するuserIdやメールに属しているかは確認してなかったんだ。だから、私のユーザー名とパスワードでログインしてJWTを取得して、それをリクエストに送ることができたんだ。IANAWD: 管理者トークンが管理者アクションを認証できるより適切なものってあるの?

もしかしたら違うことを聞いたかもしれないけど、特に俺のドックスがあの不穏なサイトに載ってたのを見たらね。HNのトップに行くためにドックスされるのって結構普通なの?

今、そこに卍の魚があるよ。みんな魚の形に入れることでフィルターを通過してるんだ: https://drawafish.com/rank.html?userId=1754341779700_log2xle... 編集: もう削除されたけど。

その魚は仏陀の手が加わってる感じだね。