Protecting Your Site With Feature Policy
Protecting Your Site With Feature Policy
Rachel Andrew
One of the web platform features highlighted at the recent Chrome Dev Summit was Feature Policy, which aims to “allow site authors to selectively enable and disable use of various browser features and APIs.” In this article, I’ll take a look at what that means for web developers, with some practical examples.
In his introductory article on the Google Developers site, Eric Bidelman describes Feature Policy as the following:
“The feature policies themselves are little opt-in agreements between developer and browser that can help foster our goals of building (and maintaining) high-quality web apps.”
The specification has been developed at Google by as part of the Web Platform Incubator Group activity. The aim of Feature Policy is for us, as web developers, to be able to state our usage of a web platform feature, explicitly to the browser. By doing so, we make an agreement about our use, or non-use of this particular feature. Based on this the browser can act to block certain features, or report back to us that a feature it did not expect to see is being used.
Examples might include:
- I am embedding an iframe and I do not want the embedded site to be able to access the camera of my visitor;
- I want to catch situations where unoptimized images are deployed to my site via the CMS;
- There are many developers working on my project, and I would like to know if they use outdated APIs such as
document.write
.
All of these things can be tracked, blocked or reported on as part of Feature Policy.
How To Use Feature Policy
In order to use Feature Policy, the browser needs to know two things: which feature you are creating a policy for, and how you want that feature to be handled.
Feature-Policy: <directive> <allowlist>
The <directive>
is the name of the feature that you are setting the policy on.
The current list of features (sourced from the presentation given at Chrome Dev Summit) are as follows:
- accelerometer
- ambient-light-sensor
- autoplay
- camera
- document-write
- encrypted-media
- fullscreen
- geolocation
- gyroscope
- layout-animations
- lazyload
- legacy-image-formats
- magnetometer
- midi
- oversized-images
- payment
- picture-in-picture
- speaker
- sync-script
- sync-xhr
- unoptimized-images
- unsized-media
- usb
- vertical-scroll
- vr
The <allowlist>
details how the feature can be used — if at all — and takes one or more of the following values.
*
The most liberal policy, stating that the feature will be allowed in this document, and any iframes whether from this domain or elsewhere. May only be used as a single value as it makes no sense to enable everything and also pass in a list of domains, for example.self
The feature will be available in the document and any iframes, however, the iframes must have the same origin.src
Only applicable when using an iframeallow
attribute. This allows a feature as long as the document loaded into it comes from the same origin as the URL in the iframe’s src attribute.none
Disables the feature for the document and any nested iframes. May only be used as a single value.<origin(s)>
The feature is allowed for specific origins; this means that you can specify a list of domains where the feature is allowed. The list of domains is space separated.
There are two methods by which you can enable feature policies on your site: You can send an HTTP Header, or use the allow
attribute on an iframe.
HTTP Header
Sending an HTTP Header means that you can enable a feature policy for the page or entire site setting that header, and also anything embedded in the site. Headers can be set for your entire site at the web server or can be sent from your application.
For example, if I wanted to prevent the use of the geolocation API and I was using the NGINX web server, I could edit the configuration files for my site in NGINX to add the following header, which would prevent any document in my site and any iframe embedded in from using the geolocation API.
add_header Feature-Policy "geolocation none;";
Multiple policies can be set in a single header. To prevent geolocation and vibrate but allow unsized-media
from the domain example.com I could set the following:
add_header Feature-Policy "vibrate none; geolocation none; unsized-media http://example.com;";
The allow
Attribute On iFrames
If we are primarily concerned with what happens with the content in an iframe, we can use Feature Policy on the iframe itself; this benefits from slightly better browser support at the time of writing with Chrome and Safari supporting this use.
If I am embedding a site and do not want that site to use geolocation, camera or microphone APIs then my iframe would look like the following example:
<iframe allow="geolocation 'none'; camera 'none'; microphone 'none'">
You may already be familiar with the individual attributes which control the content of iframes allowfullscreen
, allowpaymentrequest
, and allowusermedia
. These can be replaced by the Feature Policy allow
attribute, and for browser compatibility reasons you can use both on an iframe. If you do use both attributes, then the most restrictive one will apply. The Google article shows an example of an iframe that uses allowfullscreen
— meaning that the iframe is allowed to enter fullscreen, but then a conflicting Feature Policy of fullscreen none
. These conflict, so the most restrictive policy wins and this iframe would not be allowed to enter fullscreen.
<iframe allowfullscreen allow="fullscreen 'none'" src="...">
The iframe element also has a sandbox
attribute designed to manage support for many features. This feature was also added to Content Security Policy with a sandbox
value which disables all sandbox features, which can then be opted back into selectively. There is some crossover between sandbox features and those controlled by Feature Policy, and Feature Policy does not seek to duplicate those values already covered by sandbox. It does, however, address some of the limitations of sandbox by taking a more fine-grained approach to managing these policies, rather than one of turning everything off globally as one large policy set.
Feature Policy And Reporting API
Feature Policy violations can be reported via the Reporting API, which means that you could develop a comprehensive set of policies tracking feature usage across your site. This would be completely transparent to your users but give you a huge amount of information about how features were being used.
Browser Support For Feature Policy
Currently, browser support for Feature Policy is limited to Chrome, however, in many cases where you are using Feature Policy during development and when previewing sites this is not necessarily a problem.
Many of the use cases I will outline below are usable right now, without causing any impact to site visitors who are using browsers without support.
When To Use Feature Policy
I really like the idea of being able to use Feature Policy to help back up decisions made when developing the site. Decisions which may well be written up in documents such as a performance budget, or as part of a GDPR audit, but which then become something we have to remember to preserve through the life of the site. This is not always easy when multiple people work on a site; people who perhaps weren’t involved during that initial decision making, or may simply be unaware of the requirements. We think a lot about third parties managing to somehow impact our site, however, sometimes our sites need protecting from ourselves!
Keeping An Eye On Third Parties
You could prevent a third-party site from accessing the camera or microphone using a feature policy on the iframe with the allow
attribute. If the reason for embedding that site has nothing to do with those features, then disabling them means that the site can never start to ask for those. This could then be linked with your processes for ensuring GDPR compliance. As you audit the privacy impact of your site, you can build in processes for locking down the access of third parties by way of feature policy — giving you and your visitors additional security and peace of mind.
This usage does rely on browser support for Feature Policy to block the usage. However, you could use Feature Policy reporting mode to inform you of usage of these APIs if the third party changed what they would be doing. This would give you a very quick heads-up — essentially as soon as the first person using Chrome hits the site.
Selectively Enabling Features
We also might want to selectively enable some features which are normally blocked. Perhaps we wish to allow an iframe loading content from another site to use the geolocation feature in the browser. Chrome by default blocks this, but if you are loading content from a trusted site you could enable the cross-origin request using Feature Policy. This means that you can safely turn on features when loading content from another domain that is under your control.
Catching Use Of Outdated APIs And Poorly Performing Features
Feature Policy can be run in a report-only mode. It can then track usage of certain features and let you know when they are found on the site. This can be useful in many scenarios. If you have a very large site with a lot of legacy code, enabling Feature Policy would help you to track down the places that need attention. If you work with a large team (especially if developers often pull in some third party libraries of code), Feature Policy can catch things that you would rather not see on the site.
Dealing With Poorly Optimized Images
While most of the articles I’ve seen about Feature Policy concentrate on the security and privacy aspects, the features around image optimization really appealed to me, as someone who deals with a lot of content generated by technical and non-technical users. Feature Policy can be used to help protect the user experience as well as the performance of your site by preventing overly large — or unoptimized images — being downloaded by visitors.
In an ideal world, your CMS would deal with image management, ensuring that images were sensibly resized, optimized for the web and the context they will be displayed in. Real life is rarely that ideal world, however, and so sometimes the job of resizing and optimizing images is left to content editors to ensure they are not uploading huge images to the web. This is particularly an issue if you are using a static CMS with no content management layer on top of it. Even as a technical person, it is very easy to forget to resize that giant screenshot or camera image you popped into a folder as a placeholder.
Currently behind a flag in Chrome are features which can help. The idea behind these features is to highlight the problematic images so that they can be fixed — without completely breaking the site.
The unsized-media
feature policy looks for images or video which do not have a size set in the HTML or CSS. When an unsized media element loads, it can cause the content on the page to reflow.
In order to prevent any unsized media being added to the site, set the following header. Media will then be displayed with a default size of 300×150 pixels. You will see your site loading with small media, and realize you have a problem to fix.
Feature-Policy: unsized-media 'none'
See a demo (needs Chrome Canary with Experimental Web Platform Features on).
The oversized-images
feature policy checks to see that images are not much large than their container. If they are, a placeholder will be shown instead. This policy is incredibly useful to check that you are not sending huge desktop images to your mobile users.
Feature-Policy: oversized-images 'none'
See a demo (needs Chrome Canary with Experimental Web Platform Features on).
The unoptimized-images
feature policy checks to see if the data size of images in bytes is no more than 0.5x bigger than its rendering area in pixels. If this policy is enabled and images violate it, a placeholder will be shown instead of the image.
Feature-Policy: unoptimized-images 'none'
See a demo (needs Chrome Canary with Experimental Web Platform Features on).
Testing And Reporting On Feature Policy
Chrome DevTools will display a message to inform you that certain features have been blocked or enabled by a Feature Policy. If you have enabled Feature Policy on your site, you can check that this is working.
Support for Feature Policy has also been added to the Security Headers site, which means you can check for these along with headers such as Content Security Policy on your site — or other sites on the web.
There is a Chrome DevTools Extension which lets you toggle on and off different Feature Policies (also a great way to check your pages without needing to configure any headers).
If you would like to get into integrating your Feature Ppolicies with the Reporting API, then there is further information in terms of how to do this here.
Further Reading And Resources
I have found a number of resources, many of which I used when researching this article. These should give you all that you need to begin implementing Feature Policy in your own applications. If you are already using Content Security Policy, this seems an additional logical step towards controlling the way your site works with the browser to help ensure the security and privacy of people using your site. You have the added bonus of being able to use Feature Policy to help you keep on top of performance-damaging elements being added to your site over time.
- Feature Policy Specification
- Introducing Feature Policy
- View from Chrome Dev Summit
- Feature Policy on MDN
- Can I Use Feature Policy
- Feature Policy Demos
- Set up Feature-Policy, Referrer-Policy and Content Security Policy headers in Nginx
Articles on Smashing Magazine — For Web Designers And Developers