secure_headers 2.5.2 → 2.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of secure_headers might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c9f7672d8914364e8eef869c24c4fd82101944de
4
- data.tar.gz: c0e93e3380c8299eb0cef567ddebbcba2b72d1ed
3
+ metadata.gz: 294b9a718031dad10faeef1232529098e5ca6b1d
4
+ data.tar.gz: 4e937445b4e743d1e55934cf7355d99f793dd9cd
5
5
  SHA512:
6
- metadata.gz: 90011cbc58f5b045268542ef3798cd5d58ecafdb06c762c5eca118cadba2848e9520a9e583070cc3486f4e5a7ac2d1ef80822b16deaf452cfae797535f8c9580
7
- data.tar.gz: ff6e285cbec857db35dddbe110c47dbbc314ef2b937bf425bd3add5268751107e335c1f990d5c45f8915d8238b649c835109fdadb987e970653568064836efce
6
+ metadata.gz: 1873f2f27ad028125dbef4aafb27cb2b95dfdac50521e33003771ac1a62de0543fbc4f8dac1ca2001df6d0264f108ab0d3ad70572c26519da6a43b1d3bb0ea11
7
+ data.tar.gz: df5a83f54557f074f8da741b869844fabf8ae55657c08cf01d0aa3abbb01062187bbafa45061b2b69cdc9ca2606e7c819f763ec28e84527a933b8f057a172132
data/Gemfile CHANGED
@@ -3,7 +3,11 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  group :test do
6
- gem "guard-rspec", platforms: [:ruby_19, :ruby_20, :ruby_21, :ruby_22]
6
+ gem 'listen', '<= 3.0.8', :platforms => [:ruby_19, :ruby_20, :ruby_22]
7
+ gem "term-ansicolor", "< 1.4"
8
+ gem "tins", "< 1.3.4"
9
+
10
+ gem "guard-rspec", :platforms => [:ruby_19, :ruby_20, :ruby_21, :ruby_22]
7
11
  gem 'test-unit', '~> 3.0'
8
12
  gem 'rails', '3.2.22'
9
13
  gem 'sqlite3', :platforms => [:ruby, :mswin, :mingw]
data/README.md CHANGED
@@ -48,7 +48,7 @@ The following methods are going to be called, unless they are provided in a `ski
48
48
  :enforce => proc {|controller| controller.my_feature_flag_api.enabled? },
49
49
  :frame_src => "https: http:.twimg.com http://itunes.apple.com",
50
50
  :img_src => "https:",
51
- :connect_src => "wws:"
51
+ :connect_src => "wws:",
52
52
  :font_src => "'self' data:",
53
53
  :frame_src => "'self'",
54
54
  :img_src => "mycdn.com data:",
@@ -61,7 +61,7 @@ The following methods are going to be called, unless they are provided in a `ski
61
61
  :form_action => "'self' github.com",
62
62
  :frame_ancestors => "'none'",
63
63
  :plugin_types => 'application/x-shockwave-flash',
64
- :block_all_mixed_content => '' # see [http://www.w3.org/TR/mixed-content/]()
64
+ :block_all_mixed_content => '', # see [http://www.w3.org/TR/mixed-content/]()
65
65
  :report_uri => '//example.com/uri-directive'
66
66
  }
67
67
  config.hpkp = {
@@ -0,0 +1,158 @@
1
+ module SecureHeaders
2
+ module ControllerExtension
3
+ class << self
4
+ def append_features(base)
5
+ base.module_eval do
6
+ extend ClassMethods
7
+ include InstanceMethods
8
+ end
9
+ end
10
+ end
11
+
12
+ module ClassMethods
13
+ attr_writer :secure_headers_options
14
+ def secure_headers_options
15
+ if @secure_headers_options
16
+ @secure_headers_options
17
+ elsif superclass.respond_to?(:secure_headers_options) # stop at application_controller
18
+ superclass.secure_headers_options
19
+ else
20
+ {}
21
+ end
22
+ end
23
+
24
+ def ensure_security_headers options = {}
25
+ if RUBY_VERSION == "1.8.7"
26
+ warn "[DEPRECATION] secure_headers ruby 1.8.7 support will dropped in the next release"
27
+ end
28
+ self.secure_headers_options = options
29
+ hook = respond_to?(:before_action) ? :before_action : :before_filter
30
+ ::SecureHeaders::ALL_FILTER_METHODS.each do |method|
31
+ send(hook, method)
32
+ end
33
+ end
34
+ end
35
+
36
+ module InstanceMethods
37
+ def set_security_headers(options = self.class.secure_headers_options)
38
+ set_csp_header(request, options[:csp])
39
+ set_hsts_header(options[:hsts])
40
+ set_hpkp_header(options[:hpkp])
41
+ set_x_frame_options_header(options[:x_frame_options])
42
+ set_x_xss_protection_header(options[:x_xss_protection])
43
+ set_x_content_type_options_header(options[:x_content_type_options])
44
+ set_x_download_options_header(options[:x_download_options])
45
+ set_x_permitted_cross_domain_policies_header(options[:x_permitted_cross_domain_policies])
46
+ end
47
+
48
+ # set_csp_header - uses the request accessor and SecureHeader::Configuration settings
49
+ # set_csp_header(+Rack::Request+) - uses the parameter and and SecureHeader::Configuration settings
50
+ # set_csp_header(+Hash+) - uses the request accessor and options from parameters
51
+ # set_csp_header(+Rack::Request+, +Hash+)
52
+ def set_csp_header(req = nil, config=nil)
53
+ if req.is_a?(Hash) || req.is_a?(FalseClass)
54
+ config = req
55
+ end
56
+
57
+ config = self.class.secure_headers_options[:csp] if config.nil?
58
+ config = secure_header_options_for :csp, config
59
+
60
+ return if config == false
61
+
62
+ if config && config[:script_hash_middleware]
63
+ ContentSecurityPolicy.add_to_env(request, self, config)
64
+ else
65
+ csp_header = ContentSecurityPolicy.new(config, :request => request, :controller => self)
66
+ set_header(csp_header)
67
+ end
68
+ end
69
+
70
+
71
+ def prep_script_hash
72
+ if ::SecureHeaders::Configuration.script_hashes
73
+ @script_hashes = ::SecureHeaders::Configuration.script_hashes.dup
74
+ ActiveSupport::Notifications.subscribe("render_partial.action_view") do |event_name, start_at, end_at, id, payload|
75
+ save_hash_for_later payload
76
+ end
77
+
78
+ ActiveSupport::Notifications.subscribe("render_template.action_view") do |event_name, start_at, end_at, id, payload|
79
+ save_hash_for_later payload
80
+ end
81
+ end
82
+ end
83
+
84
+ def save_hash_for_later payload
85
+ matching_hashes = @script_hashes[payload[:identifier].gsub(Rails.root.to_s + "/", "")] || []
86
+
87
+ if payload[:layout]
88
+ # We're assuming an html.erb layout for now. Will need to handle mustache too, just not sure of the best way to do this
89
+ layout_hashes = @script_hashes[File.join("app", "views", payload[:layout]) + '.html.erb']
90
+
91
+ matching_hashes << layout_hashes if layout_hashes
92
+ end
93
+
94
+ if matching_hashes.any?
95
+ request.env[HASHES_ENV_KEY] = ((request.env[HASHES_ENV_KEY] || []) << matching_hashes).flatten
96
+ end
97
+ end
98
+
99
+ def set_x_frame_options_header(options=self.class.secure_headers_options[:x_frame_options])
100
+ set_a_header(:x_frame_options, XFrameOptions, options)
101
+ end
102
+
103
+ def set_x_content_type_options_header(options=self.class.secure_headers_options[:x_content_type_options])
104
+ set_a_header(:x_content_type_options, XContentTypeOptions, options)
105
+ end
106
+
107
+ def set_x_xss_protection_header(options=self.class.secure_headers_options[:x_xss_protection])
108
+ set_a_header(:x_xss_protection, XXssProtection, options)
109
+ end
110
+
111
+ def set_hsts_header(options=self.class.secure_headers_options[:hsts])
112
+ return unless request.ssl?
113
+ set_a_header(:hsts, StrictTransportSecurity, options)
114
+ end
115
+
116
+ def set_hpkp_header(options=self.class.secure_headers_options[:hpkp])
117
+ return unless request.ssl?
118
+ config = secure_header_options_for :hpkp, options
119
+
120
+ return if config == false || config.nil?
121
+
122
+ hpkp_header = PublicKeyPins.new(config)
123
+ set_header(hpkp_header)
124
+ end
125
+
126
+ def set_x_download_options_header(options=self.class.secure_headers_options[:x_download_options])
127
+ set_a_header(:x_download_options, XDownloadOptions, options)
128
+ end
129
+
130
+ def set_x_permitted_cross_domain_policies_header(options=self.class.secure_headers_options[:x_permitted_cross_domain_policies])
131
+ set_a_header(:x_permitted_cross_domain_policies, XPermittedCrossDomainPolicies, options)
132
+ end
133
+
134
+ private
135
+
136
+ # we can't use ||= because I'm overloading false => disable, nil => default
137
+ # both of which trigger the conditional assignment
138
+ def secure_header_options_for(type, options)
139
+ options.nil? ? ::SecureHeaders::Configuration.send(type) : options
140
+ end
141
+
142
+ def set_a_header(name, klass, options=nil)
143
+ options = secure_header_options_for(name, options)
144
+ return if options == false
145
+ set_header(SecureHeaders::get_a_header(klass, options))
146
+ end
147
+
148
+ def set_header(name_or_header, value=nil)
149
+ if name_or_header.is_a?(Header)
150
+ header = name_or_header
151
+ response.headers[header.name] = header.value
152
+ else
153
+ response.headers[name_or_header] = value
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end
@@ -11,7 +11,7 @@ if defined?(Rails::Railtie)
11
11
 
12
12
  initializer "secure_headers.action_controller" do
13
13
  ActiveSupport.on_load(:action_controller) do
14
- include ::SecureHeaders
14
+ include ::SecureHeaders::ControllerExtension
15
15
 
16
16
  unless Rails.application.config.action_dispatch.default_headers.nil?
17
17
  conflicting_headers.each do |header|
@@ -26,7 +26,7 @@ if defined?(Rails::Railtie)
26
26
  else
27
27
  module ActionController
28
28
  class Base
29
- include ::SecureHeaders
29
+ include ::SecureHeaders::ControllerExtension
30
30
  end
31
31
  end
32
32
  end
@@ -1,3 +1,3 @@
1
1
  module SecureHeaders
2
- VERSION = "2.5.2"
2
+ VERSION = "2.5.3"
3
3
  end
@@ -8,6 +8,7 @@ require "secure_headers/headers/x_xss_protection"
8
8
  require "secure_headers/headers/x_content_type_options"
9
9
  require "secure_headers/headers/x_download_options"
10
10
  require "secure_headers/headers/x_permitted_cross_domain_policies"
11
+ require "secure_headers/controller_extension"
11
12
  require "secure_headers/railtie"
12
13
  require "secure_headers/hash_helper"
13
14
  require "secure_headers/view_helper"
@@ -62,10 +63,7 @@ module SecureHeaders
62
63
 
63
64
  class << self
64
65
  def append_features(base)
65
- base.module_eval do
66
- extend ClassMethods
67
- include InstanceMethods
68
- end
66
+ base.send(:include, ControllerExtension)
69
67
  end
70
68
 
71
69
  def header_hash(options = nil)
@@ -92,149 +90,4 @@ module SecureHeaders
92
90
  end
93
91
  end
94
92
 
95
- module ClassMethods
96
- attr_writer :secure_headers_options
97
- def secure_headers_options
98
- if @secure_headers_options
99
- @secure_headers_options
100
- elsif superclass.respond_to?(:secure_headers_options) # stop at application_controller
101
- superclass.secure_headers_options
102
- else
103
- {}
104
- end
105
- end
106
-
107
- def ensure_security_headers options = {}
108
- if RUBY_VERSION == "1.8.7"
109
- warn "[DEPRECATION] secure_headers ruby 1.8.7 support will dropped in the next release"
110
- end
111
- self.secure_headers_options = options
112
- hook = respond_to?(:before_action) ? :before_action : :before_filter
113
- ALL_FILTER_METHODS.each do |method|
114
- send(hook, method)
115
- end
116
- end
117
- end
118
-
119
- module InstanceMethods
120
- def set_security_headers(options = self.class.secure_headers_options)
121
- set_csp_header(request, options[:csp])
122
- set_hsts_header(options[:hsts])
123
- set_hpkp_header(options[:hpkp])
124
- set_x_frame_options_header(options[:x_frame_options])
125
- set_x_xss_protection_header(options[:x_xss_protection])
126
- set_x_content_type_options_header(options[:x_content_type_options])
127
- set_x_download_options_header(options[:x_download_options])
128
- set_x_permitted_cross_domain_policies_header(options[:x_permitted_cross_domain_policies])
129
- end
130
-
131
- # set_csp_header - uses the request accessor and SecureHeader::Configuration settings
132
- # set_csp_header(+Rack::Request+) - uses the parameter and and SecureHeader::Configuration settings
133
- # set_csp_header(+Hash+) - uses the request accessor and options from parameters
134
- # set_csp_header(+Rack::Request+, +Hash+)
135
- def set_csp_header(req = nil, config=nil)
136
- if req.is_a?(Hash) || req.is_a?(FalseClass)
137
- config = req
138
- end
139
-
140
- config = self.class.secure_headers_options[:csp] if config.nil?
141
- config = secure_header_options_for :csp, config
142
-
143
- return if config == false
144
-
145
- if config && config[:script_hash_middleware]
146
- ContentSecurityPolicy.add_to_env(request, self, config)
147
- else
148
- csp_header = ContentSecurityPolicy.new(config, :request => request, :controller => self)
149
- set_header(csp_header)
150
- end
151
- end
152
-
153
-
154
- def prep_script_hash
155
- if ::SecureHeaders::Configuration.script_hashes
156
- @script_hashes = ::SecureHeaders::Configuration.script_hashes.dup
157
- ActiveSupport::Notifications.subscribe("render_partial.action_view") do |event_name, start_at, end_at, id, payload|
158
- save_hash_for_later payload
159
- end
160
-
161
- ActiveSupport::Notifications.subscribe("render_template.action_view") do |event_name, start_at, end_at, id, payload|
162
- save_hash_for_later payload
163
- end
164
- end
165
- end
166
-
167
- def save_hash_for_later payload
168
- matching_hashes = @script_hashes[payload[:identifier].gsub(Rails.root.to_s + "/", "")] || []
169
-
170
- if payload[:layout]
171
- # We're assuming an html.erb layout for now. Will need to handle mustache too, just not sure of the best way to do this
172
- layout_hashes = @script_hashes[File.join("app", "views", payload[:layout]) + '.html.erb']
173
-
174
- matching_hashes << layout_hashes if layout_hashes
175
- end
176
-
177
- if matching_hashes.any?
178
- request.env[HASHES_ENV_KEY] = ((request.env[HASHES_ENV_KEY] || []) << matching_hashes).flatten
179
- end
180
- end
181
-
182
- def set_x_frame_options_header(options=self.class.secure_headers_options[:x_frame_options])
183
- set_a_header(:x_frame_options, XFrameOptions, options)
184
- end
185
-
186
- def set_x_content_type_options_header(options=self.class.secure_headers_options[:x_content_type_options])
187
- set_a_header(:x_content_type_options, XContentTypeOptions, options)
188
- end
189
-
190
- def set_x_xss_protection_header(options=self.class.secure_headers_options[:x_xss_protection])
191
- set_a_header(:x_xss_protection, XXssProtection, options)
192
- end
193
-
194
- def set_hsts_header(options=self.class.secure_headers_options[:hsts])
195
- return unless request.ssl?
196
- set_a_header(:hsts, StrictTransportSecurity, options)
197
- end
198
-
199
- def set_hpkp_header(options=self.class.secure_headers_options[:hpkp])
200
- return unless request.ssl?
201
- config = secure_header_options_for :hpkp, options
202
-
203
- return if config == false || config.nil?
204
-
205
- hpkp_header = PublicKeyPins.new(config)
206
- set_header(hpkp_header)
207
- end
208
-
209
- def set_x_download_options_header(options=self.class.secure_headers_options[:x_download_options])
210
- set_a_header(:x_download_options, XDownloadOptions, options)
211
- end
212
-
213
- def set_x_permitted_cross_domain_policies_header(options=self.class.secure_headers_options[:x_permitted_cross_domain_policies])
214
- set_a_header(:x_permitted_cross_domain_policies, XPermittedCrossDomainPolicies, options)
215
- end
216
-
217
- private
218
-
219
- # we can't use ||= because I'm overloading false => disable, nil => default
220
- # both of which trigger the conditional assignment
221
- def secure_header_options_for(type, options)
222
- options.nil? ? ::SecureHeaders::Configuration.send(type) : options
223
- end
224
-
225
- def set_a_header(name, klass, options=nil)
226
- options = secure_header_options_for(name, options)
227
- return if options == false
228
- set_header(SecureHeaders::get_a_header(klass, options))
229
- end
230
-
231
- def set_header(name_or_header, value=nil)
232
- if name_or_header.is_a?(Header)
233
- header = name_or_header
234
- response.headers[header.name] = header.value
235
- else
236
- response.headers[name_or_header] = value
237
- end
238
- end
239
- end
240
93
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: secure_headers
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.2
4
+ version: 2.5.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Neil Matatall
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-19 00:00:00.000000000 Z
11
+ date: 2016-11-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -138,6 +138,7 @@ files:
138
138
  - fixtures/rails_4_1_8/vendor/assets/javascripts/.keep
139
139
  - fixtures/rails_4_1_8/vendor/assets/stylesheets/.keep
140
140
  - lib/secure_headers.rb
141
+ - lib/secure_headers/controller_extension.rb
141
142
  - lib/secure_headers/hash_helper.rb
142
143
  - lib/secure_headers/header.rb
143
144
  - lib/secure_headers/headers/content_security_policy.rb