Skip to content

フロア図アップロードのファイル種別を検証する - #17

Merged
uswebk merged 2 commits into
mainfrom
feature/upload-image-validation
Jul 16, 2026
Merged

フロア図アップロードのファイル種別を検証する#17
uswebk merged 2 commits into
mainfrom
feature/upload-image-validation

Conversation

@uswebk

@uswebk uswebk commented Jul 14, 2026

Copy link
Copy Markdown
Owner

概要

OSS公開前のセキュリティレビューで見つかった問題の修正。

フロア図アップロードの検証(Stored XSS対策)

従来はアップロードされたファイルを無検証のまま、クライアント指定の拡張子でディスク保存し /uploads から無認証配信していたため、HTML や SVG を置くことで APIオリジン(認証Cookieが載るオリジン)上での Stored XSS が可能だった。

  • image-size によるバイナリ内容の判定で PNG / JPEG / WebP のみ許可(クライアント申告のファイル名・MIMEは信用しない)
  • 判定不能・許可外の形式は 400 Unsupported image format で拒否(従来は判定失敗を握り潰して保存を続行していた)
  • 保存拡張子は検出形式からサーバー側で決定。表示用の planImageName は従来どおり元ファイル名を保持
  • SVG は image-size で検出されるがスクリプトを含められるため意図的に除外

多層防御・フェイルセーフ

  • /uploads 配信に X-Content-Type-Options: nosniff を付与
  • APP_ENV 未設定時の既定を localprod に修正(コメントの「未設定は安全側でprod扱い」と実装が矛盾していた。.env.exampleAPP_ENV=local があるためローカル開発には影響なし)

テスト

  • pnpm typecheck / APIテスト72件パス
  • 実バッファで確認: PNGは通過、HTMLは判定例外で拒否、SVGは type: "svg" 検出されるがホワイトリスト外で拒否

🤖 Generated with Claude Code

uswebk and others added 2 commits July 15, 2026 00:13
- アップロードされたバイナリの内容をimage-sizeで判定し、PNG/JPEG/WebPのみ許可する。
  従来は無検証で保存・/uploadsから配信していたため、HTML/SVG等を置くことで
  APIオリジン上のStored XSSが可能だった
- 保存拡張子はクライアントのファイル名ではなく検出形式から決定する
- /uploads配信に X-Content-Type-Options: nosniff を付与
- APP_ENV未設定時の既定をコメント通りprod(フェイルセーフ)に修正

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- 画像差し替え時に旧ファイルをストレージから削除する
- 画像検証ロジックを切り出しユニットテストを追加
- accept にサーバー側で許可済みの WebP を追加
- 保存・公開失敗時にスナックバーでエラー表示(413・形式エラーはi18nメッセージ)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@uswebk
uswebk merged commit 95fa155 into main Jul 16, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant