diff --git a/CHANGELOG.md b/CHANGELOG.md index 41ddc15f..4b9e5eef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,64 @@ +## 3.4.1 Named Appends + +### Small bugfix + +If your CSP did not define a script/style-src and you tried to use a script/style nonce, the nonce would be added to the page but it would not be added to the CSP. A workaround is to define a script/style src but now it should add the missing directive (and populate it with the default-src). + +### 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. + +```ruby +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| + if request.controller_instance.current_user.in_test_bucket? + SecureHeaders.override_x_frame_options(request, "DENY") + { 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: + +```ruby +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.): + +```ruby +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 +``` + ## 3.4.0 the frame-src/child-src transition for Firefox. Handle the `child-src`/`frame-src` transition semi-intelligently across versions. I think the code best descibes the behavior here: diff --git a/README.md b/README.md index 7e908c22..5a65a50f 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,7 @@ 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 diff --git a/secure_headers.gemspec b/secure_headers.gemspec index b1055ce1..d43aca1e 100644 --- a/secure_headers.gemspec +++ b/secure_headers.gemspec @@ -1,7 +1,7 @@ # -*- encoding: utf-8 -*- Gem::Specification.new do |gem| gem.name = "secure_headers" - gem.version = "3.4.0" + gem.version = "3.4.1" gem.authors = ["Neil Matatall"] gem.email = ["neil.matatall@gmail.com"] gem.description = 'Security related headers all in one gem.'