Permalink
e98d8f1 Oct 4, 2016
1 contributor

Users who have contributed to this file

108 lines (84 sloc) 3.58 KB

Named Appends

Named Appends are blocks of code that can be reused and composed during requests. e.g. If a certain partial is rendered conditionally, and the csp needs to be adjusted for that partial, you can create a named append for that situation. The value returned by the block will be passed into append_content_security_policy_directives. The current request object is passed as an argument to the block for even more flexibility.

def show
  if include_widget?
    @widget = widget.render
    use_content_security_policy_named_append(:widget_partial)
  end
end


SecureHeaders::Configuration.named_append(:widget_partial) do |request|
  SecureHeaders.override_x_frame_options(request, "DENY")
  if request.controller_instance.current_user.in_test_bucket?
    { child_src: %w(beta.thirdpartyhost.com) }
  else
    { child_src: %w(thirdpartyhost.com) }
  end
end

You can use as many named appends as you would like per request, but be careful because order of inclusion matters. Consider the following:

SecureHeader::Configuration.default do |config|
  config.csp = { default_src: %w('self')}
end

SecureHeaders::Configuration.named_append(:A) do |request|
  { default_src: %w(myhost.com) }
end

SecureHeaders::Configuration.named_append(:B) do |request|
  { script_src: %w('unsafe-eval') }
end

The following code will produce different policies due to the way policies are normalized (e.g. providing a previously undefined directive that inherits from default-src, removing host source values when * is provided. Removing 'none' when additional values are present, etc.):

def index
  use_content_security_policy_named_append(:A)
  use_content_security_policy_named_append(:B)
  # produces default-src 'self' myhost.com; script-src 'self' myhost.com 'unsafe-eval';
end

def show
  use_content_security_policy_named_append(:B)
  use_content_security_policy_named_append(:A)
  # produces default-src 'self' myhost.com; script-src 'self' 'unsafe-eval';
end

Named overrides

Named overrides serve two purposes:

  • To be able to refer to a configuration by simple name.
  • By precomputing the headers for a named configuration, the headers generated once and reused over every request.

To use a named override, drop a SecureHeaders::Configuration.override block outside of method definitions and then declare which named override you'd like to use. You can even override an override.

class ApplicationController < ActionController::Base
  SecureHeaders::Configuration.default do |config|
    config.csp = {
      default_src: %w('self'),
      script_src: %w(example.org)
    }
  end

  # override default configuration
  SecureHeaders::Configuration.override(:script_from_otherdomain_com) do |config|
    config.csp[:script_src] << "otherdomain.com"
  end

  # overrides the :script_from_otherdomain_com configuration
  SecureHeaders::Configuration.override(:another_config, :script_from_otherdomain_com) do |config|
    config.csp[:script_src] << "evenanotherdomain.com"
  end
end

class MyController < ApplicationController
  def index
    # Produces default-src 'self'; script-src example.org otherdomain.com
    use_secure_headers_override(:script_from_otherdomain_com)
  end

  def show
    # Produces default-src 'self'; script-src example.org otherdomain.org evenanotherdomain.com
    use_secure_headers_override(:another_config)
  end
end

By default, a no-op configuration is provided. No headers will be set when this default override is used.

class MyController < ApplicationController
  def index
    SecureHeaders.opt_out_of_all_protection(request)
  end
end