MDNのドキュメントなどでWebの仕様を追っていると、普段見落としがちな仕組みに改めて気付かされることがあります。今回は、HTTPヘッダーの「Sec-Fetch-User」について、その論理的な背景を整理します。

「そもそもユーザー側で偽装できるヘッダーに、セキュリティ上の意味はあるのか?」という疑問から出発し、Webにおける「アクセス」と「アクション」の明確な違いについて考察します。

Sec-Fetch-User ヘッダーとは何か?

Sec-Fetch-User は、ブラウザがサーバーへリクエストを送信する際に付与される「フェッチメタデータリクエストヘッダー」の一つです。

仕様は非常にシンプルで、**「そのリクエストが、ユーザーのクリックなどの直接的な操作(アクティベーション)によって発生した場合は ?1 という値がセットされる」**というものです。逆に、JavaScriptなどによる自動遷移の場合は、このヘッダー自体が省略されます。

2019年頃のGoogle Chrome 76から段階的に導入され、現在では主要な全ブラウザで標準的にサポートされています。

「偽装できるから無意味」ではない理由

このヘッダーの仕様を見たとき、ある疑問が浮かぶはずです。 curl コマンドやブラウザの拡張機能を使えば、ユーザー側で簡単に Sec-Fetch-User: ?1 を偽装できるのだから、セキュリティ対策としては無意味ではないか?」

確かにユーザー自身が直接偽造することは可能です。しかし、このヘッダーの真の目的は、ユーザー自身からの直接的な攻撃を防ぐことではなく、CSRF(クロスサイトリクエストフォージェリ)からシステムとユーザーを保護することにあります。

ブラウザの堅牢な仕様が守る防衛線

CSRF攻撃は、攻撃者が用意した罠サイトを踏ませることで、被害者のブラウザ(と正規のCookie)を利用して、標的のサーバーへ意図しないリクエストを送信させる手法です。

ここで重要になるのが、Sec-Fetch-User が**「禁止リクエストヘッダー(Forbidden request header)」**であるという事実です。

ブラウザの厳格な仕様により、Sec- から始まるヘッダーは、JavaScript(fetch API など)からプログラムで書き換えたり付与したりすることが一切できません。付与の判断はブラウザの内部処理のみが行います。

つまり、攻撃者が罠サイトにスクリプトを仕込み、裏側で勝手にリクエストを飛ばそうとしても、ユーザーの明確なクリック操作を伴わないため Sec-Fetch-User: ?1 を捏造することは不可能なのです。サーバー側でこのヘッダーの有無を検証すれば、スクリプトによる自動送信を確実にブロックできます。

「アクセス」は歓迎し、「アクション」は厳格に防ぐ

では、「Sec-Fetch-User がないリクエストはすべて遮断すればよいのか?」というと、それは適切ではありません。ここで重要になるのが、Webトラフィックにおける**「アクセス」と「アクション」の分離**です。

  • アクセス(GETリクエスト等) リンクを踏んで記事を読むなど、システムの状態を変更しない安全なリクエストです。外部のサイトから自動遷移で流入してきても、それは単なるアクセス増(PV増)であり、歓迎すべきものです。
  • アクション(POST / PUT / DELETEリクエスト等) データの削除、リソースの変更、決済など、システムの状態を書き換えるリクエストです。これらが外部から意図せず実行されることは、致命的なシステム破壊や不正操作に直結します。

実践的な防御のアプローチ

すべてのトラフィックを一律で弾くのではなく、「システムの状態を変更する重要なエンドポイント」に対してのみ、厳格な検証を行うのがセオリーです。

サポート切れの古いブラウザからの正当なリクエストを弾いてしまうリスクも考慮し、Sec-Fetch-Site (送信元のサイト情報)などの他のヘッダーと組み合わせながら、「外部サイトから来た、状態を変更する、ユーザー操作を伴わないリクエスト」だけをピンポイントで遮断するロジックを組むのが理想的です。

まとめ

最新のフレームワークやインフラの構築手法に目が行きがちですが、ブラウザが標準で提供している基礎的なセキュリティ機構を正しく理解することは非常に重要です。

ブラウザの仕様をきちんと理解して検証ロジックを組むことで、正当なトラフィックの取りこぼしを防ぎつつ、堅牢なシステムを構築できます。