Permissions-Policy 標頭實際上能鎖定什麼
一份實用指南,說明你可以限制哪些瀏覽器功能、哪些無法控制,以及如何在不破壞實用功能的情況下部署這個標頭。
目錄
簡短版本
Permissions-Policy 是一個 HTTP 回應標頭,讓網站可以限制對特定瀏覽器功能的存取:相機、麥克風、地理位置、fullscreen、payment、感測器,以及一長串較小型的 API。
它不是通用的隱私防護罩。它不會阻止所有追蹤、封鎖 cookies、防止網路請求,或讓第三方 JavaScript 變得安全。它能做好的事情範圍更窄,但仍然有價值:降低你自己的頁面與嵌入式 frame 可使用的瀏覽器能力。
這很重要,因為現代網站是由分析片段、媒體嵌入、聊天小工具、同意管理器、廣告腳本、地圖、付款流程與內部實驗拼接而成。這些元件大多不需要存取強大的裝置 API。良好的 policy 會把這件事明確化。
如果你已經在 production 中檢查標頭,請搭配直接檢查實際回應。我們的在 production 中除錯 redirects 與 HTTP headers 的小工具組涵蓋了這裡真正重要的習慣:檢查瀏覽器實際收到什麼,而不是你的設定檔說應該發生什麼。
Permissions-Policy 控制什麼
這個標頭控制對具名瀏覽器功能的存取。確切清單會隨時間改變,因為瀏覽器 API 也會變動,但常見的 directives 包括:
cameramicrophonegeolocationfullscreenpaymentusbbluetoothaccelerometergyroscopemagnetometerscreen-wake-lockclipboard-readclipboard-writepublickey-credentials-getinterest-cohort在較舊的討論中會出現,如今多半已成歷史
一個 directive 可以允許某項功能不提供給任何人、提供給目前 origin,或提供給選定的 origins。例如:
Permissions-Policy: camera=(), microphone=(), geolocation=(self)
這表示 camera 與 microphone 對該文件及其巢狀 browsing contexts 停用,而 geolocation 只允許相同 origin 使用。
一個較寬鬆的範例:
Permissions-Policy: geolocation=(self "https://maps.example"), fullscreen=(self "https://video.example")
這允許你自己的 origin 與一個指定的地圖供應商使用 geolocation,也允許你自己的 origin 加上一個影片供應商請求 fullscreen。
此 policy 由瀏覽器評估。如果某項功能不被允許,使用該 API 的 JavaScript 應該會失敗,或表現得像該功能不可用。確切的失敗模式取決於 API。有時 promise 會 reject。有時某項能力只是看起來無法使用。
它能在你自己的頁面上鎖定什麼
在 first-party 頁面上,Permissions-Policy 最有用的地方是作為護欄。它會降低意外或非預期程式碼的影響範圍。
例如,行銷頁面大概不需要麥克風、相機、Bluetooth、USB、動作感測器或 payment APIs。你可以全域拒絕這些功能:
Permissions-Policy: camera=(), microphone=(), bluetooth=(), usb=(), payment=(), accelerometer=(), gyroscope=(), magnetometer=()
這不會讓頁面上的每個 script 都變得可信。它的意思是,如果 tag manager 實驗、遭入侵的 dependency,或貼上的小工具嘗試呼叫受限制的 API,瀏覽器不應授予它存取權。
對於有許多貢獻者的團隊來說,這是一個有用的預設值。它把討論從模糊的信任轉向明確的能力。如果未來某項功能真的需要相機,就必須有人變更 policy 並說明原因。
這是正確類型的摩擦。
它能在 iframes 中鎖定什麼
這個標頭在嵌入式內容周圍尤其有用。
瀏覽器原本就會把 iframes 視為獨立的 browsing contexts,但嵌入式第三方內容如果被 policy 與 iframe attributes 允許,仍然可以請求強大的功能。Permissions-Policy 讓父頁面可以設定上限。
例如,如果你的頁面嵌入影片播放器、支援小工具與地圖,你可以避免讓每個 frame 都存取每項功能。你可能只允許影片 frame 使用 fullscreen,只允許地圖 frame 使用 geolocation。
有兩個層次需要理解:
- HTTP
Permissions-Policy標頭會為文件設定 policy。 - iframe
allowattribute 可以將特定功能委派給某個 frame,但只能在父層 policy 允許的範圍內。
一個簡單的 iframe 可能像這樣:
<iframe src="https://video.example/embed/123" allow="fullscreen"></iframe>
如果你的標頭完全拒絕 fullscreen,iframe attribute 無法覆寫這項拒絕。如果你的標頭允許該 origin 使用 fullscreen,iframe attribute 就可以委派它。
這種階層關係是此標頭值得使用的原因之一。它讓平台或安全團隊可以設定全站邊界,同時仍允許產品團隊在需要時啟用特定嵌入內容。
它無法鎖定什麼
這是團隊有時會高估此標頭的地方。
Permissions-Policy 不會取代 content security policy。它不會決定哪些 scripts 可以載入。它不會阻止 script 透過網路傳送資料。它不會清理 HTML。它不會防止 XSS。它不會封鎖表單垃圾訊息。如果問題是表單濫用,請從為什麼你的聯絡表單是最大的垃圾訊息責任中描述的機制開始,而不是從這個標頭開始。
它也不會取代 cookie 治理。Cookies、local storage、consent、third-party embeds 與瀏覽器追蹤防護是不同議題。如果你正在廣泛檢視隱私控制,cookie 環境值得另外處理;實務上的變更可參考 2026 年 cookies 發生了什麼變化,以及該如何應對。
最重要的是,Permissions-Policy 不會讓第三方 JavaScript 變得私密。如果你把第三方 script 載入到你的 first-party 頁面,它通常會以你的頁面權限執行,並受其他瀏覽器限制與你的安全標頭約束。拒絕相機存取是好事。但這不會阻止該 script 讀取 DOM 內容、觀察使用者動作,或發出被允許的網路請求。
為此,你需要不同的控制:謹慎選擇供應商、CSP、sandboxed iframes、適用時使用 Subresource Integrity、資料最小化,以及無聊但必要的審查。
合理的預設 policy
沒有一個適合所有網站的通用標頭,但多數內容與行銷網站可以從嚴格開始。
合理的第一版:
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=(), bluetooth=(), accelerometer=(), gyroscope=(), magnetometer=(), screen-wake-lock=()
然後只加回網站實際使用的功能。
例如:
- 使用 Payment Request API 的商店可能需要
payment=(self)。 - 位置查找器可能需要
geolocation=(self)或可信任的地圖 origin。 - 會議應用程式可能需要
camera=(self)與microphone=(self)。 - 以影片為主的網站可能需要
fullscreen=(self "https://trusted-video.example")。
重點不是從 checklist 複製一個龐大的 policy 然後宣稱完成。請從你的功能盤點開始。哪些頁面需要哪些瀏覽器能力?哪些嵌入內容需要委派?如果某些功能被請求,哪些會令人意外?
如何在不破壞功能的情況下部署
像部署任何其他 production 標頭一樣推出它:要有意識、有步驟。
1. 盤點功能使用情況
搜尋你的 codebase 中的瀏覽器 API 呼叫,例如 getUserMedia、geolocation、requestFullscreen、PaymentRequest、Web Bluetooth、WebUSB 與 wake lock APIs。
接著檢查第三方嵌入內容。影片、地圖、付款與身分識別供應商的文件通常會提到必要的 iframe allow 值。
2. 從低風險環境開始
在 staging 加入嚴格標頭,並測試核心流程。留意瀏覽器 console 訊息。瀏覽器通常會在某項功能被 permissions policy 封鎖時回報。
3. 必要時使用頁面特定 policies
如果你的產品有非常不同的頁面類型,不要強迫使用一個全域 policy。Blog、checkout、map page 與 video room 可能需要不同能力。
多數 web servers、frameworks 與 edge platforms 都可以依 path 條件式設定標頭。這通常比為了單一功能而削弱整個網站更乾淨。
4. 驗證真實回應
標頭可能被 CDNs、reverse proxies、app servers 與 middleware 新增、覆寫、重複或移除。請在瀏覽器 DevTools 或使用 command-line tools 檢查最終回應。
也要測試嵌入式 contexts。頂層頁面看起來正確,不保證 iframe 收到了你預期的委派。
5. 記錄例外
每個被允許的功能都應該有 owner 與理由。這聽起來很官僚,直到六個月後,沒有人記得為什麼 geolocation 曾經對一個已不再出現在頁面上的 vendor domain 開放。
常見語法錯誤
現代標頭語法很精簡,但很容易有些微寫錯。
使用空括號拒絕某項功能:
Permissions-Policy: microphone=()
使用 self 表示目前 origin:
Permissions-Policy: geolocation=(self)
使用加上引號的 origins 指定特定外部 origins:
Permissions-Policy: fullscreen=(self "https://video.example")
避免依賴舊的 Feature-Policy 範例,除非你是有意支援 legacy behavior。較舊的標頭使用不同語法,並不是你今天應該圍繞設計的目標。
也請記得,瀏覽器支援會因 directive 而異。某個瀏覽器可能支援此標頭,但不支援特定功能 directive。這很正常。請把這個標頭視為 defense-in-depth 措施,而不是你唯一的隱私或安全控制。
<!-- tool-cta:start -->
💡 試試這個: 使用 Get Headers 驗證你的 Permissions-Policy 是否按預期傳送,它會顯示伺服器正在傳送的原始回應標頭。
<!-- tool-cta:end -->
實際的隱私價值
Permissions-Policy 的隱私價值,不在於讓網站匿名或沒有追蹤器。它做不到。
它的價值在於縮小對敏感瀏覽器能力的存取。位置、相機、麥克風、裝置感測器、本機硬體 API 與付款流程都很強大。多數頁面不需要它們。許多嵌入式元件永遠不應該能夠要求它們。
這是真實的改善。它減少意外提示、限制不必要的能力暴露,並在新功能發布時,提供團隊一個可具體審查的 artifact。
這個標頭的最佳版本很無聊:預設嚴格,只有在面向使用者的功能需要時才放寬,並作為正常 release process 的一部分進行測試。