Một trang web không nên mặc định trao camera, microphone, vị trí hay fullscreen cho mọi đoạn mã và iframe mà nó nhúng. Header Permissions-Policy cho phép website đặt ranh giới capability ngay tại trình duyệt: feature nào bị tắt hoàn toàn, feature nào chỉ dành cho chính origin, và frame bên thứ ba nào được quyền sử dụng.
Policy này không tự cấp quyền cho website. Người dùng vẫn có quyền từ chối camera, microphone hoặc vị trí; HTTPS, permission prompt và các điều kiện của từng API vẫn còn nguyên. Permissions Policy chỉ đặt thêm một trần quyền: nếu policy cấm, code không thể vượt qua bằng cách xin người dùng.
1. Permissions Policy giải quyết vấn đề gì?
Đặc tả Permissions Policy của W3C định nghĩa cơ chế bật hoặc tắt có chọn lọc các browser feature/API cho document và nội dung nhúng. Cơ chế này trước đây có tên Feature Policy; cú pháp header hiện đại đã thay đổi.
Giả sử trang sản phẩm nhúng video, bản đồ, chat hỗ trợ và analytics. Nếu không có policy rõ ràng, việc một dependency thay đổi hoặc một iframe được thêm nhầm có thể mở rộng capability ngoài chủ đích. Permissions Policy biến kỳ vọng “analytics không cần microphone” thành quy tắc được trình duyệt enforce.
Policy là giới hạn tối đa, không phải nút “Allow” thay người dùng. Một feature chỉ hoạt động khi policy cho phép, browser hỗ trợ, trang đáp ứng điều kiện bảo mật và người dùng cấp quyền nếu API yêu cầu.
2. Ba allowlist quan trọng: rỗng, self và origin cụ thể
Permissions-Policy: camera=(), microphone=(), geolocation=(self), fullscreen=(self "https://video.example")
| Cú pháp | Ý nghĩa | Dùng khi |
|---|---|---|
feature=() | Tắt feature cho document và các frame con | Ứng dụng không có nhu cầu hợp lệ |
feature=(self) | Cho phép origin của document | Chỉ code first-party cần feature |
feature=(self "https://a.example") | Header cho phép thêm origin chính xác | Một nhà cung cấp nhúng đã được duyệt |
feature=* | Cho phép mọi origin theo semantics của feature | Hiếm khi phù hợp với capability nhạy cảm |
Origin gồm scheme, host và port. https://video.example không tự bao gồm mọi subdomain hay một port khác. Đây là đặc tính có ích: hãy liệt kê nhỏ nhất có thể thay vì dùng wildcard để “sửa nhanh” một iframe bị lỗi.
3. Header và iframe allow là hai lớp giao nhau
Response header đặt policy cho top-level document và giới hạn tối đa có thể truyền xuống. Thuộc tính allow trên từng <iframe> đặt container policy cho frame cụ thể:
Permissions-Policy: camera=(self "https://meet.example"), microphone=(self "https://meet.example"), geolocation=()
<iframe
src="https://meet.example/room/123"
allow="camera https://meet.example; microphone https://meet.example; fullscreen"
sandbox="allow-scripts allow-same-origin allow-forms"
title="Cuộc họp trực tuyến">
</iframe>
Origin xuất hiện trong header chưa đủ để frame cross-origin sử dụng feature; frame còn phải được delegate qua allow. Ngược lại, allow không thể nới rộng một feature đã bị header cha chặn. Document bên trong cũng có thể tự gửi policy chặt hơn.
Thuộc tính allow="camera; microphone" thường dùng allowlist mặc định gắn với origin trong src. Viết origin tường minh giúp việc review rõ hơn, nhất là khi frame có thể navigate. Nếu src chuyển sang origin không nằm trong policy, capability không nên âm thầm đi theo.
4. Bắt đầu bằng inventory, không bằng danh sách header trên mạng
Mỗi policy-controlled feature có default allowlist và mức hỗ trợ trình duyệt riêng. Tên feature cũng phát triển theo tiêu chuẩn. Vì vậy không nên chép một header dài từ blog rồi cho rằng mọi directive đều được enforce giống nhau.
- Liệt kê first-party code, iframe và third-party script đang dùng capability nào.
- Ghi owner và luồng người dùng chứng minh nhu cầu.
- Tắt trước các feature nhạy cảm chắc chắn không dùng.
- Giới hạn feature còn lại về
self. - Delegate từng origin/frame bên thứ ba sau khi kiểm thử.
Một baseline thận trọng cho website nội dung không có gọi video hoặc bản đồ có thể là:
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=(), serial=()
Đây chỉ là ví dụ. Trước khi dùng, kiểm tra feature identifier và browser support hiện tại cho tập trình duyệt của sản phẩm. Directive không được user agent nhận diện có thể bị bỏ qua; header tồn tại không chứng minh mọi capability đã bị khóa.
5. Đừng nhầm Permissions Policy với permission prompt
Ba quyết định xảy ra ở các lớp khác nhau:
| Lớp | Câu hỏi | Ví dụ |
|---|---|---|
| Permissions Policy | Document/frame này có được phép dùng feature? | Chỉ frame họp được dùng camera |
| Permission của người dùng | Người dùng có đồng ý cho origin truy cập? | Allow camera lần này |
| Logic ứng dụng | User/account có được thực hiện hành động? | Chỉ thành viên phòng họp được tham gia |
Policy không thay authentication hoặc authorization. Việc một frame được phép gọi API camera không có nghĩa người dùng đã cấp camera, càng không chứng minh tài khoản được quyền vào cuộc họp.
6. Cấu hình trong Nginx và ứng dụng PHP
Nginx có thể thêm header trên các response HTML thuộc ứng dụng:
add_header Permissions-Policy \
'camera=(), microphone=(), geolocation=(self), fullscreen=(self "https://video.example")' \
always;
PHP có thể tạo một header cố định:
$directives = [
'camera=()',
'microphone=()',
'geolocation=(self)',
'fullscreen=(self "https://video.example")',
];
header('Permissions-Policy: '.implode(', ', $directives));
Ưu tiên một nguồn cấu hình duy nhất. Nếu CDN, Nginx và ứng dụng cùng thêm header, kết quả có thể khó quan sát và khó rollback. Kiểm tra response cuối cùng từ bên ngoài hạ tầng, không chỉ unit test của ứng dụng.
7. Permissions Policy không thay iframe sandbox và CSP
iframe sandboxhạn chế script, form, navigation, popup và nhiều hành vi của frame.- Content Security Policy kiểm soát nguồn tài nguyên, script và các sink liên quan.
- Permissions Policy kiểm soát feature/capability mà document hoặc frame có thể sử dụng.
Ba cơ chế giải quyết ba trục khác nhau và thường nên dùng cùng nhau. Một iframe được phép camera vẫn cần sandbox phù hợp nếu nội dung không hoàn toàn tin cậy. Một CSP mạnh cũng không tự cấm geolocation. Ngược lại, tắt microphone không ngăn frame chạy script độc hại.
8. Thiết kế policy theo capability, không theo nhà cung cấp
Tránh cấu hình kiểu “cho iframe A mọi thứ vì A là đối tác”. Hãy hỏi từng capability:
- Video player cần fullscreen nhưng có thật sự cần camera và microphone không?
- Bản đồ cần geolocation hay chỉ nhận tọa độ do ứng dụng truyền?
- Widget thanh toán cần payment capability hay chỉ redirect tới trang riêng?
- Chat hỗ trợ có cần clipboard, display capture hoặc autoplay không?
Capability review nhỏ hơn vendor review. Khi thay nhà cung cấp, đội ngũ biết chính xác contract nào phải chuyển; khi vendor bổ sung SDK mới, browser không tự cấp feature ngoài policy.
9. Rollout mà không làm hỏng production
Bản đặc tả mới định nghĩa Permissions-Policy-Report-Only và reporting, nhưng mức hỗ trợ có thể khác giữa trình duyệt. Đừng dựa duy nhất vào report-only nếu chưa xác minh trên browser matrix của mình. Một kế hoạch thực dụng:
- Thu thập inventory từ source, tag manager, danh sách iframe và hành vi thực tế.
- Bật policy nhỏ trên staging; test luồng camera, microphone, vị trí, payment và fullscreen.
- Canary một nhóm route hoặc tỷ lệ traffic; theo dõi lỗi JavaScript và conversion.
- Enforce các directive chắc chắn như capability không dùng trước.
- Thêm directive theo từng đợt, ghi owner và ngày review cho mỗi ngoại lệ.
Thông báo vi phạm trên console thường chỉ là điểm bắt đầu. Cần test kết quả người dùng: permission prompt có xuất hiện đúng lúc, video call có media, bản đồ có fallback, iframe fullscreen hoạt động và luồng thanh toán không bị kẹt.
10. Các lỗi cấu hình thường gặp
- Dùng cú pháp Feature Policy cũ như
camera 'none'trong header mới thay vìcamera=(). - Cho origin trong header nhưng quên
allowtrên iframe cross-origin. - Thêm
allowvà kỳ vọng nó vượt qua policy chặt hơn từ document cha. - Dùng wildcard cho camera/microphone chỉ để sửa nhanh một integration.
- Coi subdomain là origin giống nhau;
selfkhông có nghĩa “mọi subdomain”. - Không kiểm tra redirect hoặc navigation của iframe sang origin khác.
- Giả định directive không báo lỗi đồng nghĩa đã được browser hỗ trợ và enforce.
11. Checklist trước khi phát hành
- Header production có cú pháp hiện đại và chỉ xuất hiện theo cấu hình dự kiến.
- Danh sách feature dựa trên nhu cầu thật và browser support được kiểm chứng.
- Capability nhạy cảm không dùng đã đặt allowlist rỗng.
- Origin third-party được liệt kê chính xác, không dùng wildcard không cần thiết.
- Mỗi iframe có
allow,sandboxvàtitlephù hợp. - Đã test cả trang top-level, iframe same-origin, cross-origin và sau redirect.
- Permission bị từ chối có UI fallback; không bỏ qua kiểm tra bảo mật hoặc nghiệp vụ.
- Có canary, metric lỗi, rollback và lịch rà soát exception.
Permissions Policy tốt không cố liệt kê mọi API của trình duyệt; nó thể hiện contract capability nhỏ nhất mà sản phẩm thật sự cần. Dùng header để đặt trần toàn trang, dùng iframe allow để delegate chính xác, rồi kết hợp sandbox, CSP và permission của người dùng để tạo nhiều lớp kiểm soát độc lập.




Chưa có bình luận. Hãy là người đầu tiên chia sẻ ý kiến.