Permissions-Policy ヘッダーで実際に制限できるもの
制限できるブラウザー機能、制御できないもの、有用な機能を壊さずにヘッダーを展開する方法を整理した実践ガイド。
目次
要点
Permissions-Policy は HTTP レスポンスヘッダーで、サイトが特定のブラウザー機能へのアクセスを制限できるようにします。対象には、カメラ、マイク、位置情報、全画面表示、決済、センサー、そして多数の小規模な API が含まれます。
これは汎用的なプライバシー保護ではありません。すべてのトラッキングを止めたり、Cookie をブロックしたり、ネットワークリクエストを防いだり、サードパーティ JavaScript を安全にしたりするものではありません。得意なことはもっと限定的ですが、それでも価値があります。自分たちのページや埋め込みフレームで利用できるブラウザー機能を減らせることです。
これが重要なのは、現代の Web サイトが、分析スニペット、メディア埋め込み、チャットウィジェット、同意管理ツール、広告スクリプト、地図、決済フロー、社内実験などを組み合わせて作られているからです。これらのコンポーネントの大半は、強力なデバイス API へのアクセスを必要としません。適切なポリシーは、そのことを明示します。
本番環境でヘッダーをすでに確認しているなら、この作業は実際のレスポンスを直接確認することと組み合わせてください。本番環境でリダイレクトと HTTP ヘッダーをデバッグするための小さなツールキットでは、ここで重要になる習慣を扱っています。設定ファイル上で起きるはずのことではなく、ブラウザーが実際に受け取るものを確認する、という習慣です。
Permissions-Policy が制御するもの
このヘッダーは、名前付きのブラウザー機能へのアクセスを制御します。ブラウザー API は変化するため、正確な一覧も時間とともに変わりますが、一般的なディレクティブには次のようなものがあります。
cameramicrophonegeolocationfullscreenpaymentusbbluetoothaccelerometergyroscopemagnetometerscreen-wake-lockclipboard-readclipboard-writepublickey-credentials-get- 古い議論では
interest-cohortもありましたが、現在ではほぼ歴史的なものです
ディレクティブでは、ある機能を誰にも許可しない、現在のオリジンに許可する、または選択したオリジンに許可する、という指定ができます。例を挙げます。
Permissions-Policy: camera=(), microphone=(), geolocation=(self)
これは、カメラとマイクがそのドキュメントおよび入れ子のブラウジングコンテキストで無効化され、位置情報は同一オリジンにのみ許可されることを意味します。
より許可範囲の広い例です。
Permissions-Policy: geolocation=(self "https://maps.example"), fullscreen=(self "https://video.example")
これは、自分のオリジンと指定した地図プロバイダー 1 つに位置情報の利用を許可し、自分のオリジンと動画プロバイダーに全画面表示の要求を許可します。
ポリシーはブラウザーによって評価されます。機能が許可されていない場合、その API を使う JavaScript は失敗するか、利用不能であるかのように振る舞うはずです。具体的な失敗の仕方は API によって異なります。Promise が reject されることもあります。単に機能が利用できるように見えない場合もあります。
自分たちのページで制限できるもの
ファーストパーティページでは、Permissions-Policy はガードレールとして最も有用です。偶発的なコードや予期しないコードによる影響範囲を小さくできます。
たとえばマーケティングページでは、通常、マイク、カメラ、Bluetooth、USB、モーションセンサー、決済 API は必要ありません。これらの機能を全体で拒否できます。
Permissions-Policy: camera=(), microphone=(), bluetooth=(), usb=(), payment=(), accelerometer=(), gyroscope=(), magnetometer=()
これによってページ上のすべてのスクリプトが信頼できるようになるわけではありません。意味するのは、タグマネージャーの実験、侵害された依存関係、貼り付けられたウィジェットが制限対象 API を呼び出そうとしても、ブラウザーはそのアクセスを許可しないはずだということです。
多くのコントリビューターがいるチームにとって、これは有用なデフォルトです。曖昧な信頼の話を、明示的な機能権限の話に変えられます。将来の機能が本当にカメラを必要とするなら、誰かがポリシーを変更し、その理由を説明しなければなりません。
それは望ましい種類の摩擦です。
iframe で制限できるもの
このヘッダーは、埋め込みコンテンツの周辺で特に有用になります。
ブラウザーはすでに iframe を別個のブラウジングコンテキストとして扱いますが、埋め込まれたサードパーティコンテンツは、ポリシーと iframe 属性で許可されていれば、強力な機能を要求できます。Permissions-Policy により、親ページは上限を設定できます。
たとえば、ページに動画プレーヤー、サポートウィジェット、地図を埋め込んでいる場合、すべてのフレームにすべての機能へのアクセスを与える必要はありません。全画面表示は動画フレームにのみ許可し、位置情報は地図フレームにのみ許可する、といった指定ができます。
理解しておくべき層は 2 つあります。
- HTTP の
Permissions-Policyヘッダーがドキュメントのポリシーを設定します。 - iframe の
allow属性は特定の機能をフレームに委譲できますが、親ポリシーが許可する範囲内に限られます。
単純な iframe は次のようになります。
<iframe src="https://video.example/embed/123" allow="fullscreen"></iframe>
ヘッダーが全画面表示を完全に拒否している場合、iframe 属性でその拒否を上書きすることはできません。ヘッダーがそのオリジンに全画面表示を許可していれば、iframe 属性で委譲できます。
この階層構造は、このヘッダーを使う価値がある理由の 1 つです。プラットフォームチームやセキュリティチームがサイト全体の境界を設定しつつ、必要な場所ではプロダクトチームが特定の埋め込みを有効にできます。
制限できないもの
ここで、チームはこのヘッダーを過大評価しがちです。
Permissions-Policy はコンテンツセキュリティポリシーの代替ではありません。どのスクリプトを読み込めるかを決めるものではありません。スクリプトがネットワーク経由でデータを送信することを止めるものでもありません。HTML をサニタイズしません。XSS を防ぎません。フォームスパムをブロックしません。フォーム悪用が問題なら、このヘッダーではなく、問い合わせフォームが最大のスパムリスクになる理由で説明している仕組みから着手してください。
Cookie ガバナンスの代替にもなりません。Cookie、local storage、同意、サードパーティ埋め込み、ブラウザーのトラッキング保護は、それぞれ別の問題です。プライバシー制御を広く見直しているなら、Cookie の状況は個別に確認する価値があります。実践的な変更点は、2026 年に Cookie はどう変わったか、そして何をすべきかで扱っています。
最も重要なのは、Permissions-Policy がサードパーティ JavaScript をプライベートにするわけではないという点です。サードパーティスクリプトをファーストパーティページに読み込むと、通常、そのスクリプトは他のブラウザー制約やセキュリティヘッダーの範囲内で、ページの権限を持って実行されます。カメラアクセスを拒否するのは良いことです。しかし、それによってそのスクリプトが DOM コンテンツを読んだり、ユーザー操作を観察したり、許可されたネットワークリクエストを行ったりすることは止まりません。
そのためには別の制御が必要です。慎重なベンダー選定、CSP、sandboxed iframes、適用可能な場合の Subresource Integrity、データ最小化、そして地味ですが必要なレビューです。
妥当なデフォルトポリシー
すべてのサイトに合う普遍的なヘッダーはありませんが、多くのコンテンツサイトやマーケティングサイトは制限的に始められます。
最初の案として妥当なのは次のようなものです。
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=(), bluetooth=(), accelerometer=(), gyroscope=(), magnetometer=(), screen-wake-lock=()
そのうえで、サイトが実際に使うものだけを戻します。
たとえば次のようになります。
- Payment Request API を使うストアでは、
payment=(self)が必要になる場合があります。 - 店舗検索などでは、
geolocation=(self)または信頼できる地図オリジンが必要になる場合があります。 - 会議アプリでは、
camera=(self)とmicrophone=(self)が必要になる場合があります。 - 動画中心のサイトでは、
fullscreen=(self "https://trusted-video.example")が必要になる場合があります。
重要なのは、チェックリストから巨大なポリシーをコピーして終わりにしないことです。まず機能の棚卸しから始めてください。どのページがどのブラウザー機能を必要としているのか。どの埋め込みに委譲が必要なのか。要求されたら意外に感じる機能はどれか。
壊さずに展開する方法
これは他の本番ヘッダーと同じように、意図的に展開してください。
1. 機能の利用状況を棚卸しする
コードベース内で、getUserMedia、geolocation、requestFullscreen、PaymentRequest、Web Bluetooth、WebUSB、wake lock API などのブラウザー API 呼び出しを検索します。
次に、サードパーティ埋め込みを確認します。動画、地図、決済、ID プロバイダーのドキュメントには、必要な iframe の allow 値が記載されていることがよくあります。
2. 低リスクな環境から始める
ステージング環境に制限的なヘッダーを追加し、主要なユーザージャーニーをテストします。ブラウザーコンソールのメッセージに注意してください。ブラウザーは、機能が permissions policy によってブロックされた場合に報告することがよくあります。
3. 必要に応じてページ単位のポリシーを使う
プロダクトに大きく異なるページ種別があるなら、1 つのグローバルポリシーを無理に適用しないでください。ブログ、チェックアウト、地図ページ、動画ルームでは、おそらく必要な機能が異なります。
ほとんどの Web サーバー、フレームワーク、エッジプラットフォームでは、パスごとに条件付きでヘッダーを設定できます。1 つの機能のためにサイト全体を弱めるより、そのほうがすっきりすることが多いです。
4. 実際のレスポンスを確認する
ヘッダーは CDN、リバースプロキシ、アプリケーションサーバー、ミドルウェアによって追加、上書き、重複、削除されることがあります。ブラウザーの DevTools やコマンドラインツールで最終レスポンスを確認してください。
埋め込みコンテキストもテストしてください。トップレベルページが正しく見えることは、iframe が意図した委譲を受け取ったことを保証しません。
5. 例外を文書化する
許可されたすべての機能には、オーナーと理由があるべきです。これは官僚的に聞こえますが、6 か月後に、なぜ geolocation がページ上にもう見当たらないベンダードメインに開かれていたのか誰も覚えていない、という事態を避けられます。
よくある構文ミス
現代のヘッダー構文はコンパクトですが、少し間違えやすいものです。
機能を拒否するには空の括弧を使います。
Permissions-Policy: microphone=()
現在のオリジンには self を使います。
Permissions-Policy: geolocation=(self)
特定の外部オリジンには引用符付きのオリジンを使います。
Permissions-Policy: fullscreen=(self "https://video.example")
レガシーな挙動を意図的にサポートするのでない限り、古い Feature-Policy の例に依存するのは避けてください。古いヘッダーは異なる構文を使っており、今日の設計の前提にすべきものではありません。
また、ブラウザーサポートはディレクティブによって異なることも覚えておいてください。ブラウザーがヘッダーには対応していても、特定の機能ディレクティブには対応していない場合があります。それは通常のことです。このヘッダーは多層防御の一部として扱い、唯一のプライバシーまたはセキュリティ制御にしないでください。
<!-- tool-cta:start -->
💡 お試しください: Get Headers で Permissions-Policy が意図したとおりに配信されていることを確認できます。これは、サーバーが送信している生のレスポンスヘッダーを表示します。
<!-- tool-cta:end -->
実用上のプライバシー価値
Permissions-Policy のプライバシー上の価値は、サイトを匿名化したり、トラッカーなしにしたりすることではありません。そうはなりません。
価値があるのは、センシティブなブラウザー機能へのアクセスを狭められる点です。位置情報、カメラ、マイク、デバイスセンサー、ローカルハードウェア API、決済フローは強力です。ほとんどのページには不要です。多くの埋め込みコンポーネントは、それらを要求できるべきではありません。
これは実質的な改善です。偶発的なプロンプトを減らし、不要な機能露出を制限し、新しい機能がリリースされるときにチームが確認できる具体的な成果物を提供します。
このヘッダーの最良の形は退屈なものです。デフォルトでは制限的にし、ユーザー向け機能が必要とする場所でのみ緩め、通常のリリースプロセスの一部としてテストすることです。