Safari’s default media controls get blocked when applying a Content-Security-Policy

I recently ran into an unexpected road block trying to deploy a Content-Security-Policy on a website that relied on the native media controls provided for the HTML <audio> and <video> elements in Safari. The default browser-provided multimedia controls were good enough for my purposes and they provide a platform-native user experience to all users. To my surprise, I noticed that there were no usable playback control buttons in Safari on pages with a strict content security policy.

Content-Security-Policy is a HTTP response header that servers can send to indicate stricter than default security policies for their origin. To only allow a page to display images and play media from its own origin you’d send a header like this (broken onto multiple lines for readability):

Content-Security-Policy:
  default-src 'none';
    media-src 'self';
      img-src 'self'

The above example blocks media and images from other origins/domains, and even completely blocks stylesheets and scripts from running at all.

Safari 11 (for macOS and iOS 11) and Safari 12 (for macOS and iOS 12) supplies the icons for the default media control buttons as SVG files loaded over a data URI blob. Safari haven’t made any exceptions for these graphics sourced from the browser itself when processing a content security policy.

The result is that Safari blocks its own default media controls and end up not having any visible icons for them. Safari also sends a content security policy violation report, if the content security policy is configured to so. The default semi-transparent dark toolbar that should hold the icons are visible, and the click-regions for the media controls get really small when the icons fails to load.

This is clearly a bug in Safari. The browser’s own graphics are always trusted and especially in this context. The default media controls are trusted and won’t get blocked by the same content security policy in other web browsers including Firefox, Google Chrome, and Safari 10 and older. You can follow WebKit bug #191782 if you’re interested in updates on this specific issue.

You can’t use a nonce-source or hash-source to specifically allow only the assets that Safari need either. The only work-around that let you keep using the default controls for audio and videos is to lower the security level of the page by changing the policy:

Content-Security-Policy:
  default-src 'none';
    media-src 'self';
      img-src 'self' data:

This allows the loading of any image resource from any data URI that have somehow made it onto your page. This can be a security risk as a data URI is considered to be equivalent to the unsafe-inline source. This is far from perfect but it’s still a better place to be in than not having a content security policy at all.

Another work-around is to just bite the bullet and design and supply your own media controls instead of relying on Safari’s default media controls and graphics. This can be a lot of unwanted extra work when the default media controls would have worked just fine.

This issue is a good reminder that a content security policy requires ongoing monitoring as new problems and browser bugs can break core functionality of your website.