- 著者
- app-hacks
- 公開日
- 更新日
- 確認日
Cloudflare Pages / Functions / セキュリティ
Cloudflare Pages Functionsのお問い合わせ入力検証
Cloudflare Pages FunctionsでJSON、文字数、Origin、リクエストサイズ、エラー応答を検証するお問い合わせAPIの境界設計を解説します。
Cloudflare Pages Functionsのお問い合わせ入力検証
お問い合わせフォームでは、ブラウザ側の入力制限だけを信頼できません。リクエストは直接APIへ送れるため、Pages Functionの入口でメソッド、Origin、Content-Type、本文サイズ、JSONの形、各フィールドを順に検証します。メール送信やTurnstileの確認より前に入力境界を作ることで、不正な値を後段のサービスへ渡さないようにします。
最初に受け付けるリクエストを絞る
APIはフォームの想定どおりのPOSTだけを受け取ります。許可しないメソッドや別Originからのリクエストは、本文を読んだり外部サービスへ接続したりする前に止めます。
if (request.method !== 'POST') {
return json({ ok: false }, 405);
}
if (request.headers.get('Origin') !== siteOrigin) {
return json({ ok: false }, 403);
}
if (!request.headers.get('Content-Type')?.includes('application/json')) {
return json({ ok: false }, 415);
}
Originの確認はすべての不正送信を防ぐ仕組みではありませんが、サイトのフォームとして受けるリクエストの境界を明確にします。エラー時に詳細な内部条件を返しすぎると、攻撃者に検証ルールを与えるため、応答は最小限にします。
本文サイズは読み込み中にも制限する
Content-Lengthは参考になりますが、ヘッダー値だけを信用して本文を無制限に読み込んではいけません。ストリームから読むたびに合計サイズを確認し、上限を超えたら中止します。
let size = 0;
const chunks: Uint8Array[] = [];
for await (const chunk of request.body ?? []) {
size += chunk.byteLength;
if (size > 24_000) return json({ ok: false }, 413);
chunks.push(chunk);
}
上限値は、受け付ける項目の最大文字数とエンコーディングの余裕を考えて決めます。フォーム本文を画像や添付ファイルの経路にしない場合は、別のアップロードAPIと混ぜないことも重要です。
JSONの形とフィールドを個別に確認する
JSONとして解析できても、配列、null、想定外の型を受け入れるべきではありません。オブジェクトだけを受け、文字列は空白を除去してから長さと形式を確認します。
const value = await request.json();
if (!value || Array.isArray(value) || typeof value !== 'object') {
return json({ ok: false }, 400);
}
const name = typeof value.name === 'string' ? value.name.trim() : '';
const message = typeof value.message === 'string' ? value.message.trim() : '';
if (!name || name.length > 100 || message.length < 10 || message.length > 5_000) {
return json({ ok: false }, 400);
}
メールアドレス、件名、Turnstileトークンにも、用途に応じた形式と上限を設けます。検証はブラウザとFunctionの両方に置けますが、信頼境界になるのはFunction側です。
応答を一定にして保存させない
成功・失敗ともJSONとして返し、Content-TypeとCache-Control: no-storeを付けます。入力エラー、認証失敗、外部メールサービスの失敗を、利用者向けのメッセージと内部ログで分けます。レスポンスに認証情報、メールAPIの応答本文、受信先アドレスを含めません。
入力検証は迷惑送信対策やメール配信の代わりではありません。Turnstileのサーバー側検証、レート制限、送信先の認証情報管理とは別に、入口のデータを小さく正しい形に保つ役割です。各段階を分けることで、失敗時の原因も切り分けやすくなります。