[Proposal] Default Permission Policy

Recently updated an app to Rails 7 and noticed the new permission_policy.rb file. The benefits of the feature aren’t huge to me but security is all about layers and it’s a nice layer to add since I know my site will never need features such as camera, microphone, etc.

One thing I really like about the content security policy is you can specify a default policy to lock things down by default, then open things up as needed for specific capabilities. This is of course because the CSP spec has the concept of a default src while the permission policy does not seem to have a similar concept.

I would like to propose we emulate a default policy within Rails to allow developers deny by default then open things up as needed. This might allow the example policy to be simplified to:

# Rails.application.config.permissions_policy do |policy|
#   policy.default :none
#   policy.fullscreen  :self
#   policy.payment     :self, "https://secure.example.com"
# end

The advantage to doing this besides simpler config files is also to avoid developers needing to stay on top of whatever new permission is being added to the spec.

For example, the spec currently has display-capture (screen share) which is not currently in the list that Rails supports. It would be nice if a developer was taking a “deny all, open as needed” approach that as soon as display-capture is supported by Rails it will be automatically denied without them needing to update their config file (and of course if they want screen share they can open it back up).

I’m currently emulating this with the following hack:

all_permission_directives = ActionDispatch::PermissionsPolicy::const_get(:DIRECTIVES).keys

Rails.application.config.permissions_policy do |f|
  all_permission_directives.each { f.public_send _1, :none }

While this works it is reading a private constant (which is prone to breakage). It would be much nicer if I could just say:

Rails.application.config.permissions_policy do |f|
  policy.default :none

Then the effect is that every permission supported by Rails is denied. I’m open to coding up a PR for such a feature but wanted to get feedback if something like this is even desired or if I should just continue using my hack.