--- name: file-storage description: ファイルアップロード、S3、ファイルシステム操作を扱う際に使用。 --- # File & Storage ## 📋 実行前チェック(必須) ### このスキルを使うべきか? - [ ] ファイルアップロードを実装する? - [ ] S3連携を行う? - [ ] ファイル検証処理を実装する? - [ ] 署名付きURLを生成する? ### 前提条件 - [ ] 許可するファイルタイプを定義したか? - [ ] ファイルサイズ上限を決定したか? - [ ] 保存先を決定したか?(ローカル/S3等) ### 禁止事項の確認 - [ ] ユーザー入力のファイル名をそのまま使おうとしていないか? - [ ] 拡張子だけでファイルタイプを判断しようとしていないか? - [ ] サイズ制限なしでアップロードを許可しようとしていないか? - [ ] 機密ファイルをパブリックにしようとしていないか? --- ## トリガー - ファイルアップロード実装時 - S3連携時 - ファイル検証処理時 - 署名付きURL生成時 --- ## 🚨 鉄則 **ユーザーアップロードは信用しない。検証必須。** --- ## アップロード検証 ```typescript // ⚠️ 必須チェック const ALLOWED_TYPES = ['image/jpeg', 'image/png', 'image/webp']; const MAX_SIZE = 5 * 1024 * 1024; // 5MB function validateUpload(file: File) { // MIMEタイプ(⚠️ 拡張子だけで判断しない) if (!ALLOWED_TYPES.includes(file.mimetype)) { throw new Error('Invalid file type'); } // サイズ if (file.size > MAX_SIZE) { throw new Error('File too large'); } // ファイル名サニタイズ const safeName = sanitizeFilename(file.originalname); } ``` --- ## S3署名付きURL ```typescript import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; const url = await getSignedUrl(s3Client, new GetObjectCommand({ Bucket: 'my-bucket', Key: 'file.pdf' }), { expiresIn: 3600 }); // 1時間 ``` --- ## 🚫 禁止事項まとめ - ユーザー入力ファイル名のそのまま使用 - 拡張子だけでのファイルタイプ判断 - サイズ制限なしのアップロード - 機密ファイルのパブリック公開