履歴書・職務経歴書の「安全な添付」運用|ファイル受け取りの設計・スキャン・保管・廃棄まで

採用フォームにファイル添付を置くなら、セキュリティ(悪意ファイルの遮断)個人情報保護(安全な保管・廃棄)を同時に満たす必要があります。本記事は、現場でそのまま使える受け取り→検査→保管→配布→廃棄の実装テンプレをまとめました。

前提:ファイル添付はなぜ危険か

  • 拡張子偽装・MIME偽装で悪意あるスクリプトやマクロを混入できる
  • アップロード後の直リンク公開インライン表示で情報漏えい/XSSになる
  • 履歴書には高密度の個人情報が含まれ、保存・共有・廃棄の全工程が法的/倫理的な配慮対象

「ファイルタイプは拡張子やContent-Typeだけに頼らず検証」「サイズ/ファイル名/保存先の制限」「アップロードは認証ユーザーのみ」— OWASP File Upload Cheat Sheet の基本原則。
参考:OWASP File Upload Cheat Sheet

安全設計の全体像(推奨フロー)

  1. 許可ルール:拡張子/サイズ/ページ数などの事前チェック
  2. アップロード:アプリ経由ではなくストレージ直送(プリサインドURL)
  3. 検査:到着直後にウイルス/マクロ検査、NGは隔離
  4. 保管:非公開バケット/フォルダ、暗号化+アクセス制御
  5. 配布:採用担当のみ期限付きダウンロード常に添付配布はリンク経由
  6. 廃棄:選考終了・所定日数で自動削除、ログは法定範囲で保存

1) 許可ポリシー(拡張子/サイズ/名前)

  • 拡張子は .pdf を推奨(Office系はマクロを起動しない方針)。どうしても受ける場合は .docx/.xlsx のみ
  • 最大サイズ:5〜10MB程度(GTM/GA4の送信にも影響しづらい
  • ファイル名はサーバ生成のランダム名に置換。原本名はDBにメタとして保存
  • 拡張子ホワイトリスト+シグネチャ(マジックナンバー)検査を併用

「許可拡張子のホワイトリスト」「MIME/マジックナンバーの検査」「保存名の再生成」「サイズ上限」などはOWASP推奨。
参考:OWASP File Upload Cheat SheetUnrestricted File Upload

2) S3プリサインドURL直送(安全な受け取り)

アプリサーバにファイル本体を通さず、ストレージへ直接アップロードする方式にすると、帯域/可用性/権限分離の面で堅牢になります。

  • 有効期限の短いプリサインドURLを発行(数分〜最長7日、用途に応じて)
  • キーは応募ID/日付で名前空間分離、上書き禁止(ユニークキー)
  • アップロード後は即スキャン→結果OKなら「確認済み」タグを付与

「プリサインドURLは時間制限と操作限定で管理」— AWS公式。
参考:S3 presigned URL(AWS Docs)Best Practices(AWS Prescriptive Guidance)[PDF]

3) ウイルス/マクロ検査(到着直後に自動)

  • ClamAV 等のエンジンでスキャン(更新シグネチャで定期アップデート)
  • スキャンは非同期キューで実行、結果がNGなら隔離フォルダへ移動し担当に通知
  • 合格ファイルのみ「safe=true」メタタグを付与、UIは「審査中/合格/隔離」を表示

ClamAVはデーモン(clamd)で高速スキャンとオンアクセススキャンを提供。
参考:ClamAV ScanningOn-Access Scanning

4) 非公開保管と暗号化・アクセス制御

  • ストレージは完全非公開(公開URLなし)。ダウンロードは都度発行の期限付きリンクのみ
  • 暗号化:サーバサイド暗号化(SSE-KMS等)+転送時TLS
  • アクセスは採用担当ロールのみ、アクセスログ(誰がいつ何をDL)を保存

5) 廃棄ポリシー(保管期間・消去)

  • 個人情報の保存期間は法律で一律に定まっていませんが、利用目的がなくなったら遅滞なく消去に努めるのが原則
  • 第三者提供の「提供記録」は原則3年間保存(該当時)
  • 採用実務では「選考終了から60〜180日で自動削除」等、明文化して同意を取得

「保存期間の規定はないが、必要がなくなれば遅滞なく消去に努める(法22条)」/「第三者提供の記録は原則3年保存」— 個人情報保護委員会FAQ。
参考:取得した個人情報は、いつ廃棄?第三者提供の記録保存(3年)

6) ダウンロード配布の安全策

  • インライン表示を避け、Content-Disposition: attachment常にダウンロード
  • ファイル名は面接ID_候補者イニシャル_日付.pdf等、過度な個人情報を入れない
  • メール添付は原則禁止。期限付きリンクを共有(社外共有時はパス付き+閲覧期限)

7) 実装スニペット(要点)

サーバ側:MIME/シグネチャ検査(例:Node.js)

// pseudo: magic number check (PDFだけ許可)
import fs from 'node:fs/promises';
const PDF_SIG = Buffer.from([0x25,0x50,0x44,0x46]); // %PDF
async function isPdf(filePath){
  const fd = await fs.open(filePath, 'r'); const b = Buffer.alloc(4);
  await fd.read(b, 0, 4, 0); await fd.close();
  return b.equals(PDF_SIG);
}

プリサインドURL発行(例:サーバ)

// pseudo: AWS SDK v3
// 1) 応募IDで名前空間分離、2) Content-Typeを固定、3) 有効期限短め
const key = `apply/${applyId}/${crypto.randomUUID()}.pdf`;
const url = await getPresignedUrl({ key, contentType: 'application/pdf', expiresIn: 300 /*sec*/ });

スキャンワークフロー(擬似)

// S3 Putイベント → Queue → Scanner(ClamAV) → タグ付け
if (clamScan(file).infected) {
  moveTo('quarantine/', key); tag(key, {safe: 'false', reason: 'virus'});
  notify('security@company', `隔離: ${key}`);
} else {
  tag(key, {safe: 'true'});
}

8) よくある失敗と回避策

  • 拡張子だけチェック必ずシグネチャ検査を併用
  • 公開バケットに保存 → 非公開+期限付きリンクに統一
  • スキャン前に社内展開 → 検査通過まではダウンロード不可の状態に
  • 廃棄が手作業 → ライフサイクルルール/定期ジョブで自動削除

9) 運用チェックリスト

  • 許可拡張子/サイズ/命名の定義書があり、UIとAPIが同じルール
  • アップロードはプリサインドURL、サーバはメタのみ受け取る
  • 到着直後に自動スキャン、OK/NGをタグで可視化
  • 非公開ストレージ+暗号化+役割ベースのアクセス制御
  • 期限付きURLのみで配布(メール添付は原則禁止)
  • 保存/廃棄ポリシーが合意・周知・自動化されている
  • アクセス/配布ログを保存(第三者提供に該当する場合の記録は3年

参考・一次情報

このテンプレを導入すれば、CVRを落とさずに安全性と法令配慮を両立できます。実装のサンプル(AWS/Lambda/ClamAV)もご用意できます。必要なら声をかけてください。

コメント

この記事へのコメントはありません。

最近の記事
おすすめ記事1
PAGE TOP