secure_headers 6.3.4 → 7.3.0

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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -2
  3. data/Gemfile +2 -0
  4. data/README.md +81 -15
  5. data/lib/secure_headers/configuration.rb +64 -13
  6. data/lib/secure_headers/headers/clear_site_data.rb +31 -33
  7. data/lib/secure_headers/headers/content_security_policy.rb +80 -46
  8. data/lib/secure_headers/headers/content_security_policy_config.rb +17 -58
  9. data/lib/secure_headers/headers/cookie.rb +4 -6
  10. data/lib/secure_headers/headers/expect_certificate_transparency.rb +20 -22
  11. data/lib/secure_headers/headers/policy_management.rb +66 -18
  12. data/lib/secure_headers/headers/referrer_policy.rb +20 -22
  13. data/lib/secure_headers/headers/reporting_endpoints.rb +54 -0
  14. data/lib/secure_headers/headers/strict_transport_security.rb +13 -15
  15. data/lib/secure_headers/headers/x_content_type_options.rb +14 -16
  16. data/lib/secure_headers/headers/x_download_options.rb +14 -16
  17. data/lib/secure_headers/headers/x_frame_options.rb +14 -16
  18. data/lib/secure_headers/headers/x_permitted_cross_domain_policies.rb +14 -16
  19. data/lib/secure_headers/headers/x_xss_protection.rb +14 -16
  20. data/lib/secure_headers/middleware.rb +11 -7
  21. data/lib/secure_headers/railtie.rb +11 -8
  22. data/lib/secure_headers/task_helper.rb +65 -0
  23. data/lib/secure_headers/version.rb +1 -1
  24. data/lib/secure_headers/view_helper.rb +7 -6
  25. data/lib/secure_headers.rb +26 -2
  26. data/lib/tasks/tasks.rake +4 -53
  27. data/secure_headers.gemspec +19 -7
  28. metadata +38 -70
  29. data/.github/ISSUE_TEMPLATE.md +0 -41
  30. data/.github/PULL_REQUEST_TEMPLATE.md +0 -20
  31. data/.github/workflows/build.yml +0 -24
  32. data/.github/workflows/github-release.yml +0 -28
  33. data/.gitignore +0 -13
  34. data/.rspec +0 -3
  35. data/.rubocop.yml +0 -4
  36. data/.ruby-gemset +0 -1
  37. data/.ruby-version +0 -1
  38. data/CODE_OF_CONDUCT.md +0 -46
  39. data/CONTRIBUTING.md +0 -41
  40. data/Guardfile +0 -13
  41. data/Rakefile +0 -32
  42. data/docs/cookies.md +0 -65
  43. data/docs/hashes.md +0 -64
  44. data/docs/named_overrides_and_appends.md +0 -104
  45. data/docs/per_action_configuration.md +0 -139
  46. data/docs/sinatra.md +0 -25
  47. data/docs/upgrading-to-3-0.md +0 -42
  48. data/docs/upgrading-to-4-0.md +0 -35
  49. data/docs/upgrading-to-5-0.md +0 -15
  50. data/docs/upgrading-to-6-0.md +0 -50
  51. data/spec/lib/secure_headers/configuration_spec.rb +0 -121
  52. data/spec/lib/secure_headers/headers/clear_site_data_spec.rb +0 -87
  53. data/spec/lib/secure_headers/headers/content_security_policy_spec.rb +0 -190
  54. data/spec/lib/secure_headers/headers/cookie_spec.rb +0 -179
  55. data/spec/lib/secure_headers/headers/expect_certificate_transparency_spec.rb +0 -42
  56. data/spec/lib/secure_headers/headers/policy_management_spec.rb +0 -264
  57. data/spec/lib/secure_headers/headers/referrer_policy_spec.rb +0 -91
  58. data/spec/lib/secure_headers/headers/strict_transport_security_spec.rb +0 -33
  59. data/spec/lib/secure_headers/headers/x_content_type_options_spec.rb +0 -31
  60. data/spec/lib/secure_headers/headers/x_download_options_spec.rb +0 -29
  61. data/spec/lib/secure_headers/headers/x_frame_options_spec.rb +0 -36
  62. data/spec/lib/secure_headers/headers/x_permitted_cross_domain_policies_spec.rb +0 -48
  63. data/spec/lib/secure_headers/headers/x_xss_protection_spec.rb +0 -47
  64. data/spec/lib/secure_headers/middleware_spec.rb +0 -117
  65. data/spec/lib/secure_headers/view_helpers_spec.rb +0 -191
  66. data/spec/lib/secure_headers_spec.rb +0 -516
  67. data/spec/spec_helper.rb +0 -64
@@ -2,7 +2,7 @@
2
2
  module SecureHeaders
3
3
  class XFOConfigError < StandardError; end
4
4
  class XFrameOptions
5
- HEADER_NAME = "X-Frame-Options".freeze
5
+ HEADER_NAME = "x-frame-options".freeze
6
6
  SAMEORIGIN = "sameorigin"
7
7
  DENY = "deny"
8
8
  ALLOW_FROM = "allow-from"
@@ -10,22 +10,20 @@ module SecureHeaders
10
10
  DEFAULT_VALUE = SAMEORIGIN
11
11
  VALID_XFO_HEADER = /\A(#{SAMEORIGIN}\z|#{DENY}\z|#{ALLOW_ALL}\z|#{ALLOW_FROM}[:\s])/i
12
12
 
13
- class << self
14
- # Public: generate an X-Frame-Options header.
15
- #
16
- # Returns a default header if no configuration is provided, or a
17
- # header name and value based on the config.
18
- def make_header(config = nil, user_agent = nil)
19
- return if config == OPT_OUT
20
- [HEADER_NAME, config || DEFAULT_VALUE]
21
- end
13
+ # Public: generate an X-Frame-Options header.
14
+ #
15
+ # Returns a default header if no configuration is provided, or a
16
+ # header name and value based on the config.
17
+ def self.make_header(config = nil, user_agent = nil)
18
+ return if config == OPT_OUT
19
+ [HEADER_NAME, config || DEFAULT_VALUE]
20
+ end
22
21
 
23
- def validate_config!(config)
24
- return if config.nil? || config == OPT_OUT
25
- raise TypeError.new("Must be a string. Found #{config.class}: #{config}") unless config.is_a?(String)
26
- unless config =~ VALID_XFO_HEADER
27
- raise XFOConfigError.new("Value must be SAMEORIGIN|DENY|ALLOW-FROM:|ALLOWALL")
28
- end
22
+ def self.validate_config!(config)
23
+ return if config.nil? || config == OPT_OUT
24
+ raise TypeError.new("Must be a string. Found #{config.class}: #{config}") unless config.is_a?(String)
25
+ unless config =~ VALID_XFO_HEADER
26
+ raise XFOConfigError.new("Value must be SAMEORIGIN|DENY|ALLOW-FROM:|ALLOWALL")
29
27
  end
30
28
  end
31
29
  end
@@ -2,26 +2,24 @@
2
2
  module SecureHeaders
3
3
  class XPCDPConfigError < StandardError; end
4
4
  class XPermittedCrossDomainPolicies
5
- HEADER_NAME = "X-Permitted-Cross-Domain-Policies".freeze
5
+ HEADER_NAME = "x-permitted-cross-domain-policies".freeze
6
6
  DEFAULT_VALUE = "none"
7
7
  VALID_POLICIES = %w(all none master-only by-content-type by-ftp-filename)
8
8
 
9
- class << self
10
- # Public: generate an X-Permitted-Cross-Domain-Policies header.
11
- #
12
- # Returns a default header if no configuration is provided, or a
13
- # header name and value based on the config.
14
- def make_header(config = nil, user_agent = nil)
15
- return if config == OPT_OUT
16
- [HEADER_NAME, config || DEFAULT_VALUE]
17
- end
9
+ # Public: generate an x-permitted-cross-domain-policies header.
10
+ #
11
+ # Returns a default header if no configuration is provided, or a
12
+ # header name and value based on the config.
13
+ def self.make_header(config = nil, user_agent = nil)
14
+ return if config == OPT_OUT
15
+ [HEADER_NAME, config || DEFAULT_VALUE]
16
+ end
18
17
 
19
- def validate_config!(config)
20
- return if config.nil? || config == OPT_OUT
21
- raise TypeError.new("Must be a string. Found #{config.class}: #{config}") unless config.is_a?(String)
22
- unless VALID_POLICIES.include?(config.downcase)
23
- raise XPCDPConfigError.new("Value can only be one of #{VALID_POLICIES.join(', ')}")
24
- end
18
+ def self.validate_config!(config)
19
+ return if config.nil? || config == OPT_OUT
20
+ raise TypeError.new("Must be a string. Found #{config.class}: #{config}") unless config.is_a?(String)
21
+ unless VALID_POLICIES.include?(config.downcase)
22
+ raise XPCDPConfigError.new("Value can only be one of #{VALID_POLICIES.join(', ')}")
25
23
  end
26
24
  end
27
25
  end
@@ -2,25 +2,23 @@
2
2
  module SecureHeaders
3
3
  class XXssProtectionConfigError < StandardError; end
4
4
  class XXssProtection
5
- HEADER_NAME = "X-XSS-Protection".freeze
6
- DEFAULT_VALUE = "1; mode=block"
5
+ HEADER_NAME = "x-xss-protection".freeze
6
+ DEFAULT_VALUE = "0".freeze
7
7
  VALID_X_XSS_HEADER = /\A[01](; mode=block)?(; report=.*)?\z/
8
8
 
9
- class << self
10
- # Public: generate an X-Xss-Protection header.
11
- #
12
- # Returns a default header if no configuration is provided, or a
13
- # header name and value based on the config.
14
- def make_header(config = nil, user_agent = nil)
15
- return if config == OPT_OUT
16
- [HEADER_NAME, config || DEFAULT_VALUE]
17
- end
9
+ # Public: generate an X-Xss-Protection header.
10
+ #
11
+ # Returns a default header if no configuration is provided, or a
12
+ # header name and value based on the config.
13
+ def self.make_header(config = nil, user_agent = nil)
14
+ return if config == OPT_OUT
15
+ [HEADER_NAME, config || DEFAULT_VALUE]
16
+ end
18
17
 
19
- def validate_config!(config)
20
- return if config.nil? || config == OPT_OUT
21
- raise TypeError.new("Must be a string. Found #{config.class}: #{config}") unless config.is_a?(String)
22
- raise XXssProtectionConfigError.new("Invalid format (see VALID_X_XSS_HEADER)") unless config.to_s =~ VALID_X_XSS_HEADER
23
- end
18
+ def self.validate_config!(config)
19
+ return if config.nil? || config == OPT_OUT
20
+ raise TypeError.new("Must be a string. Found #{config.class}: #{config}") unless config.is_a?(String)
21
+ raise XXssProtectionConfigError.new("Invalid format (see VALID_X_XSS_HEADER)") unless config.to_s =~ VALID_X_XSS_HEADER
24
22
  end
25
23
  end
26
24
  end
@@ -10,6 +10,12 @@ module SecureHeaders
10
10
  req = Rack::Request.new(env)
11
11
  status, headers, response = @app.call(env)
12
12
 
13
+ # Rack::Headers is available in Rack 3.x and later
14
+ # So we should pull the headers into that structure if possible
15
+ if defined?(Rack::Headers)
16
+ headers = Rack::Headers[headers]
17
+ end
18
+
13
19
  config = SecureHeaders.config_for(req)
14
20
  flag_cookies!(headers, override_secure(env, config.cookies)) unless config.cookies == OPT_OUT
15
21
  headers.merge!(SecureHeaders.header_hash_for(req))
@@ -20,14 +26,12 @@ module SecureHeaders
20
26
 
21
27
  # inspired by https://github.com/tobmatth/rack-ssl-enforcer/blob/6c014/lib/rack/ssl-enforcer.rb#L183-L194
22
28
  def flag_cookies!(headers, config)
23
- if cookies = headers["Set-Cookie"]
24
- # Support Rails 2.3 / Rack 1.1 arrays as headers
25
- cookies = cookies.split("\n") unless cookies.is_a?(Array)
29
+ cookies = headers["Set-Cookie"]
30
+ return unless cookies
26
31
 
27
- headers["Set-Cookie"] = cookies.map do |cookie|
28
- SecureHeaders::Cookie.new(cookie, config).to_s
29
- end.join("\n")
30
- end
32
+ cookies_array = cookies.is_a?(Array) ? cookies : cookies.split("\n")
33
+ secured_cookies = cookies_array.map { |cookie| SecureHeaders::Cookie.new(cookie, config).to_s }
34
+ headers["Set-Cookie"] = cookies.is_a?(Array) ? secured_cookies : secured_cookies.join("\n")
31
35
  end
32
36
 
33
37
  # disable Secure cookies for non-https requests
@@ -4,11 +4,11 @@ if defined?(Rails::Railtie)
4
4
  module SecureHeaders
5
5
  class Railtie < Rails::Railtie
6
6
  isolate_namespace SecureHeaders if defined? isolate_namespace # rails 3.0
7
- conflicting_headers = ["X-Frame-Options", "X-XSS-Protection",
8
- "X-Permitted-Cross-Domain-Policies", "X-Download-Options",
9
- "X-Content-Type-Options", "Strict-Transport-Security",
10
- "Content-Security-Policy", "Content-Security-Policy-Report-Only",
11
- "Public-Key-Pins", "Public-Key-Pins-Report-Only", "Referrer-Policy"]
7
+ conflicting_headers = ["x-frame-options", "x-xss-protection",
8
+ "x-permitted-cross-domain-policies", "x-download-options",
9
+ "x-content-type-options", "strict-transport-security",
10
+ "content-security-policy", "content-security-policy-report-only",
11
+ "public-key-pins", "public-key-pins-report-only", "referrer-policy"]
12
12
 
13
13
  initializer "secure_headers.middleware" do
14
14
  Rails.application.config.middleware.insert_before 0, SecureHeaders::Middleware
@@ -22,9 +22,12 @@ if defined?(Rails::Railtie)
22
22
  ActiveSupport.on_load(:action_controller) do
23
23
  include SecureHeaders
24
24
 
25
- unless Rails.application.config.action_dispatch.default_headers.nil?
26
- conflicting_headers.each do |header|
27
- Rails.application.config.action_dispatch.default_headers.delete(header)
25
+ default_headers = Rails.application.config.action_dispatch.default_headers
26
+ unless default_headers.nil?
27
+ default_headers.each_key do |header|
28
+ if conflicting_headers.include?(header.downcase)
29
+ default_headers.delete(header)
30
+ end
28
31
  end
29
32
  end
30
33
  end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SecureHeaders
4
+ module TaskHelper
5
+ include SecureHeaders::HashHelper
6
+
7
+ INLINE_SCRIPT_REGEX = /(<script(\s*(?!src)([\w\-])+=([\"\'])[^\"\']+\4)*\s*>)(.*?)<\/script>/mx
8
+ INLINE_STYLE_REGEX = /(<style[^>]*>)(.*?)<\/style>/mx
9
+ INLINE_HASH_SCRIPT_HELPER_REGEX = /<%=\s?hashed_javascript_tag(.*?)\s+do\s?%>(.*?)<%\s*end\s*%>/mx
10
+ INLINE_HASH_STYLE_HELPER_REGEX = /<%=\s?hashed_style_tag(.*?)\s+do\s?%>(.*?)<%\s*end\s*%>/mx
11
+
12
+ def generate_inline_script_hashes(filename)
13
+ hashes = []
14
+
15
+ hashes.concat find_inline_content(filename, INLINE_SCRIPT_REGEX, false)
16
+ hashes.concat find_inline_content(filename, INLINE_HASH_SCRIPT_HELPER_REGEX, true)
17
+
18
+ hashes
19
+ end
20
+
21
+ def generate_inline_style_hashes(filename)
22
+ hashes = []
23
+
24
+ hashes.concat find_inline_content(filename, INLINE_STYLE_REGEX, false)
25
+ hashes.concat find_inline_content(filename, INLINE_HASH_STYLE_HELPER_REGEX, true)
26
+
27
+ hashes
28
+ end
29
+
30
+ def dynamic_content?(filename, inline_script)
31
+ !!(
32
+ (is_mustache?(filename) && inline_script =~ /\{\{.*\}\}/) ||
33
+ (is_erb?(filename) && inline_script =~ /<%.*%>/)
34
+ )
35
+ end
36
+
37
+ private
38
+
39
+ def find_inline_content(filename, regex, strip_trailing_whitespace)
40
+ hashes = []
41
+ file = File.read(filename)
42
+ file.scan(regex) do # TODO don't use gsub
43
+ inline_script = Regexp.last_match.captures.last
44
+ inline_script.gsub!(/(\r?\n)[\t ]+\z/, '\1') if strip_trailing_whitespace
45
+ if dynamic_content?(filename, inline_script)
46
+ puts "Looks like there's some dynamic content inside of a tag :-/"
47
+ puts "That pretty much means the hash value will never match."
48
+ puts "Code: " + inline_script
49
+ puts "=" * 20
50
+ end
51
+
52
+ hashes << hash_source(inline_script)
53
+ end
54
+ hashes
55
+ end
56
+
57
+ def is_erb?(filename)
58
+ filename =~ /\.erb\Z/
59
+ end
60
+
61
+ def is_mustache?(filename)
62
+ filename =~ /\.mustache\Z/
63
+ end
64
+ end
65
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SecureHeaders
4
- VERSION = "6.3.4"
4
+ VERSION = "7.3.0"
5
5
  end
@@ -147,12 +147,13 @@ module SecureHeaders
147
147
 
148
148
  def nonced_tag(type, content_or_options, block)
149
149
  options = {}
150
- content = if block
151
- options = content_or_options
152
- capture(&block)
153
- else
154
- content_or_options.html_safe # :'(
155
- end
150
+ content =
151
+ if block
152
+ options = content_or_options
153
+ capture(&block)
154
+ else
155
+ content_or_options.html_safe # :'(
156
+ end
156
157
  content_tag type, content, options.merge(nonce: _content_security_policy_nonce(type))
157
158
  end
158
159
 
@@ -11,6 +11,7 @@ require "secure_headers/headers/x_permitted_cross_domain_policies"
11
11
  require "secure_headers/headers/referrer_policy"
12
12
  require "secure_headers/headers/clear_site_data"
13
13
  require "secure_headers/headers/expect_certificate_transparency"
14
+ require "secure_headers/headers/reporting_endpoints"
14
15
  require "secure_headers/middleware"
15
16
  require "secure_headers/railtie"
16
17
  require "secure_headers/view_helper"
@@ -133,6 +134,7 @@ module SecureHeaders
133
134
  # request.
134
135
  #
135
136
  # StrictTransportSecurity is not applied to http requests.
137
+ # upgrade_insecure_requests is not applied to http requests.
136
138
  # See #config_for to determine which config is used for a given request.
137
139
  #
138
140
  # Returns a hash of header names => header values. The value
@@ -146,6 +148,11 @@ module SecureHeaders
146
148
 
147
149
  if request.scheme != HTTPS
148
150
  headers.delete(StrictTransportSecurity::HEADER_NAME)
151
+
152
+ # Remove upgrade_insecure_requests from CSP headers for HTTP requests
153
+ # as it doesn't make sense to upgrade requests when the page itself is served over HTTP
154
+ remove_upgrade_insecure_requests_from_csp!(headers, config.csp)
155
+ remove_upgrade_insecure_requests_from_csp!(headers, config.csp_report_only)
149
156
  end
150
157
  headers
151
158
  end
@@ -178,7 +185,7 @@ module SecureHeaders
178
185
  content_security_policy_nonce(request, ContentSecurityPolicy::STYLE_SRC)
179
186
  end
180
187
 
181
- # Public: Retreives the config for a given header type:
188
+ # Public: Retrieves the config for a given header type:
182
189
  #
183
190
  # Checks to see if there is an override for this request, then
184
191
  # Checks to see if a named override is used for this request, then
@@ -208,7 +215,7 @@ module SecureHeaders
208
215
 
209
216
  def config_and_target(request, target)
210
217
  config = config_for(request)
211
- target = guess_target(config) unless target
218
+ target ||= guess_target(config)
212
219
  raise_on_unknown_target(target)
213
220
  [config, target]
214
221
  end
@@ -242,6 +249,23 @@ module SecureHeaders
242
249
  def override_secure_headers_request_config(request, config)
243
250
  request.env[SECURE_HEADERS_CONFIG] = config
244
251
  end
252
+
253
+ # Private: removes upgrade_insecure_requests directive from a CSP config
254
+ # if it's present, and updates the headers hash with the modified CSP.
255
+ #
256
+ # headers - the headers hash to update
257
+ # csp_config - the CSP config to check and potentially modify
258
+ #
259
+ # Returns nothing (modifies headers in place)
260
+ def remove_upgrade_insecure_requests_from_csp!(headers, csp_config)
261
+ return if csp_config.opt_out?
262
+ return unless csp_config.directive_value(ContentSecurityPolicy::UPGRADE_INSECURE_REQUESTS)
263
+
264
+ modified_config = csp_config.dup
265
+ modified_config.update_directive(ContentSecurityPolicy::UPGRADE_INSECURE_REQUESTS, false)
266
+ header_name, value = ContentSecurityPolicy.make_header(modified_config)
267
+ headers[header_name] = value if header_name && value
268
+ end
245
269
  end
246
270
 
247
271
  # These methods are mixed into controllers and delegate to the class method
data/lib/tasks/tasks.rake CHANGED
@@ -1,58 +1,8 @@
1
1
  # frozen_string_literal: true
2
- INLINE_SCRIPT_REGEX = /(<script(\s*(?!src)([\w\-])+=([\"\'])[^\"\']+\4)*\s*>)(.*?)<\/script>/mx unless defined? INLINE_SCRIPT_REGEX
3
- INLINE_STYLE_REGEX = /(<style[^>]*>)(.*?)<\/style>/mx unless defined? INLINE_STYLE_REGEX
4
- INLINE_HASH_SCRIPT_HELPER_REGEX = /<%=\s?hashed_javascript_tag(.*?)\s+do\s?%>(.*?)<%\s*end\s*%>/mx unless defined? INLINE_HASH_SCRIPT_HELPER_REGEX
5
- INLINE_HASH_STYLE_HELPER_REGEX = /<%=\s?hashed_style_tag(.*?)\s+do\s?%>(.*?)<%\s*end\s*%>/mx unless defined? INLINE_HASH_STYLE_HELPER_REGEX
2
+ require "secure_headers/task_helper"
6
3
 
7
4
  namespace :secure_headers do
8
- include SecureHeaders::HashHelper
9
-
10
- def is_erb?(filename)
11
- filename =~ /\.erb\Z/
12
- end
13
-
14
- def is_mustache?(filename)
15
- filename =~ /\.mustache\Z/
16
- end
17
-
18
- def dynamic_content?(filename, inline_script)
19
- (is_mustache?(filename) && inline_script =~ /\{\{.*\}\}/) ||
20
- (is_erb?(filename) && inline_script =~ /<%.*%>/)
21
- end
22
-
23
- def find_inline_content(filename, regex, hashes, strip_trailing_whitespace)
24
- file = File.read(filename)
25
- file.scan(regex) do # TODO don't use gsub
26
- inline_script = Regexp.last_match.captures.last
27
- inline_script.gsub!(/(\r?\n)[\t ]+\z/, '\1') if strip_trailing_whitespace
28
- if dynamic_content?(filename, inline_script)
29
- puts "Looks like there's some dynamic content inside of a tag :-/"
30
- puts "That pretty much means the hash value will never match."
31
- puts "Code: " + inline_script
32
- puts "=" * 20
33
- end
34
-
35
- hashes << hash_source(inline_script)
36
- end
37
- end
38
-
39
- def generate_inline_script_hashes(filename)
40
- hashes = []
41
-
42
- find_inline_content(filename, INLINE_SCRIPT_REGEX, hashes, false)
43
- find_inline_content(filename, INLINE_HASH_SCRIPT_HELPER_REGEX, hashes, true)
44
-
45
- hashes
46
- end
47
-
48
- def generate_inline_style_hashes(filename)
49
- hashes = []
50
-
51
- find_inline_content(filename, INLINE_STYLE_REGEX, hashes, false)
52
- find_inline_content(filename, INLINE_HASH_STYLE_HELPER_REGEX, hashes, true)
53
-
54
- hashes
55
- end
5
+ include SecureHeaders::TaskHelper
56
6
 
57
7
  desc "Generate #{SecureHeaders::Configuration::HASH_CONFIG_FILE}"
58
8
  task :generate_hashes do |t, args|
@@ -77,6 +27,7 @@ namespace :secure_headers do
77
27
  file.write(script_hashes.to_yaml)
78
28
  end
79
29
 
80
- puts "Script hashes from " + script_hashes.keys.size.to_s + " files added to #{SecureHeaders::Configuration::HASH_CONFIG_FILE}"
30
+ file_count = (script_hashes["scripts"].keys + script_hashes["styles"].keys).uniq.count
31
+ puts "Script and style hashes from #{file_count} files added to #{SecureHeaders::Configuration::HASH_CONFIG_FILE}"
81
32
  end
82
33
  end
@@ -9,15 +9,27 @@ Gem::Specification.new do |gem|
9
9
  gem.version = SecureHeaders::VERSION
10
10
  gem.authors = ["Neil Matatall"]
11
11
  gem.email = ["neil.matatall@gmail.com"]
12
- gem.description = "Manages application of security headers with many safe defaults."
13
- gem.summary = 'Add easily configured security headers to responses
12
+ gem.summary = "Manages application of security headers with many safe defaults."
13
+ gem.description = 'Add easily configured security headers to responses
14
14
  including content-security-policy, x-frame-options,
15
15
  strict-transport-security, etc.'
16
- gem.homepage = "https://github.com/twitter/secureheaders"
17
- gem.license = "Apache Public License 2.0"
18
- gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
19
- gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
20
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
16
+ gem.homepage = "https://github.com/github/secure_headers"
17
+ gem.metadata = {
18
+ "bug_tracker_uri" => "https://github.com/github/secure_headers/issues",
19
+ "changelog_uri" => "https://github.com/github/secure_headers/blob/master/CHANGELOG.md",
20
+ "documentation_uri" => "https://rubydoc.info/gems/secure_headers",
21
+ "homepage_uri" => gem.homepage,
22
+ "source_code_uri" => "https://github.com/github/secure_headers",
23
+ "rubygems_mfa_required" => "true",
24
+ }
25
+ gem.license = "MIT"
26
+
27
+ gem.files = Dir["bin/**/*", "lib/**/*", "README.md", "CHANGELOG.md", "LICENSE", "Gemfile", "secure_headers.gemspec"]
21
28
  gem.require_paths = ["lib"]
29
+
30
+ gem.extra_rdoc_files = Dir["README.md", "CHANGELOG.md", "LICENSE"]
31
+
32
+ gem.add_dependency "cgi", ">= 0.1"
33
+
22
34
  gem.add_development_dependency "rake"
23
35
  end
metadata CHANGED
@@ -1,15 +1,28 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: secure_headers
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.3.4
4
+ version: 7.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Neil Matatall
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2022-06-28 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: cgi
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0.1'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0.1'
13
26
  - !ruby/object:Gem::Dependency
14
27
  name: rake
15
28
  requirement: !ruby/object:Gem::Requirement
@@ -24,39 +37,23 @@ dependencies:
24
37
  - - ">="
25
38
  - !ruby/object:Gem::Version
26
39
  version: '0'
27
- description: Manages application of security headers with many safe defaults.
40
+ description: |-
41
+ Add easily configured security headers to responses
42
+ including content-security-policy, x-frame-options,
43
+ strict-transport-security, etc.
28
44
  email:
29
45
  - neil.matatall@gmail.com
30
46
  executables: []
31
47
  extensions: []
32
- extra_rdoc_files: []
48
+ extra_rdoc_files:
49
+ - CHANGELOG.md
50
+ - LICENSE
51
+ - README.md
33
52
  files:
34
- - ".github/ISSUE_TEMPLATE.md"
35
- - ".github/PULL_REQUEST_TEMPLATE.md"
36
- - ".github/workflows/build.yml"
37
- - ".github/workflows/github-release.yml"
38
- - ".gitignore"
39
- - ".rspec"
40
- - ".rubocop.yml"
41
- - ".ruby-gemset"
42
- - ".ruby-version"
43
53
  - CHANGELOG.md
44
- - CODE_OF_CONDUCT.md
45
- - CONTRIBUTING.md
46
54
  - Gemfile
47
- - Guardfile
48
55
  - LICENSE
49
56
  - README.md
50
- - Rakefile
51
- - docs/cookies.md
52
- - docs/hashes.md
53
- - docs/named_overrides_and_appends.md
54
- - docs/per_action_configuration.md
55
- - docs/sinatra.md
56
- - docs/upgrading-to-3-0.md
57
- - docs/upgrading-to-4-0.md
58
- - docs/upgrading-to-5-0.md
59
- - docs/upgrading-to-6-0.md
60
57
  - lib/secure_headers.rb
61
58
  - lib/secure_headers/configuration.rb
62
59
  - lib/secure_headers/hash_helper.rb
@@ -67,6 +64,7 @@ files:
67
64
  - lib/secure_headers/headers/expect_certificate_transparency.rb
68
65
  - lib/secure_headers/headers/policy_management.rb
69
66
  - lib/secure_headers/headers/referrer_policy.rb
67
+ - lib/secure_headers/headers/reporting_endpoints.rb
70
68
  - lib/secure_headers/headers/strict_transport_security.rb
71
69
  - lib/secure_headers/headers/x_content_type_options.rb
72
70
  - lib/secure_headers/headers/x_download_options.rb
@@ -75,33 +73,22 @@ files:
75
73
  - lib/secure_headers/headers/x_xss_protection.rb
76
74
  - lib/secure_headers/middleware.rb
77
75
  - lib/secure_headers/railtie.rb
76
+ - lib/secure_headers/task_helper.rb
78
77
  - lib/secure_headers/utils/cookies_config.rb
79
78
  - lib/secure_headers/version.rb
80
79
  - lib/secure_headers/view_helper.rb
81
80
  - lib/tasks/tasks.rake
82
81
  - secure_headers.gemspec
83
- - spec/lib/secure_headers/configuration_spec.rb
84
- - spec/lib/secure_headers/headers/clear_site_data_spec.rb
85
- - spec/lib/secure_headers/headers/content_security_policy_spec.rb
86
- - spec/lib/secure_headers/headers/cookie_spec.rb
87
- - spec/lib/secure_headers/headers/expect_certificate_transparency_spec.rb
88
- - spec/lib/secure_headers/headers/policy_management_spec.rb
89
- - spec/lib/secure_headers/headers/referrer_policy_spec.rb
90
- - spec/lib/secure_headers/headers/strict_transport_security_spec.rb
91
- - spec/lib/secure_headers/headers/x_content_type_options_spec.rb
92
- - spec/lib/secure_headers/headers/x_download_options_spec.rb
93
- - spec/lib/secure_headers/headers/x_frame_options_spec.rb
94
- - spec/lib/secure_headers/headers/x_permitted_cross_domain_policies_spec.rb
95
- - spec/lib/secure_headers/headers/x_xss_protection_spec.rb
96
- - spec/lib/secure_headers/middleware_spec.rb
97
- - spec/lib/secure_headers/view_helpers_spec.rb
98
- - spec/lib/secure_headers_spec.rb
99
- - spec/spec_helper.rb
100
- homepage: https://github.com/twitter/secureheaders
82
+ homepage: https://github.com/github/secure_headers
101
83
  licenses:
102
- - Apache Public License 2.0
103
- metadata: {}
104
- post_install_message:
84
+ - MIT
85
+ metadata:
86
+ bug_tracker_uri: https://github.com/github/secure_headers/issues
87
+ changelog_uri: https://github.com/github/secure_headers/blob/master/CHANGELOG.md
88
+ documentation_uri: https://rubydoc.info/gems/secure_headers
89
+ homepage_uri: https://github.com/github/secure_headers
90
+ source_code_uri: https://github.com/github/secure_headers
91
+ rubygems_mfa_required: 'true'
105
92
  rdoc_options: []
106
93
  require_paths:
107
94
  - lib
@@ -116,26 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
103
  - !ruby/object:Gem::Version
117
104
  version: '0'
118
105
  requirements: []
119
- rubygems_version: 3.0.3.1
120
- signing_key:
106
+ rubygems_version: 3.6.9
121
107
  specification_version: 4
122
- summary: Add easily configured security headers to responses including content-security-policy,
123
- x-frame-options, strict-transport-security, etc.
124
- test_files:
125
- - spec/lib/secure_headers/configuration_spec.rb
126
- - spec/lib/secure_headers/headers/clear_site_data_spec.rb
127
- - spec/lib/secure_headers/headers/content_security_policy_spec.rb
128
- - spec/lib/secure_headers/headers/cookie_spec.rb
129
- - spec/lib/secure_headers/headers/expect_certificate_transparency_spec.rb
130
- - spec/lib/secure_headers/headers/policy_management_spec.rb
131
- - spec/lib/secure_headers/headers/referrer_policy_spec.rb
132
- - spec/lib/secure_headers/headers/strict_transport_security_spec.rb
133
- - spec/lib/secure_headers/headers/x_content_type_options_spec.rb
134
- - spec/lib/secure_headers/headers/x_download_options_spec.rb
135
- - spec/lib/secure_headers/headers/x_frame_options_spec.rb
136
- - spec/lib/secure_headers/headers/x_permitted_cross_domain_policies_spec.rb
137
- - spec/lib/secure_headers/headers/x_xss_protection_spec.rb
138
- - spec/lib/secure_headers/middleware_spec.rb
139
- - spec/lib/secure_headers/view_helpers_spec.rb
140
- - spec/lib/secure_headers_spec.rb
141
- - spec/spec_helper.rb
108
+ summary: Manages application of security headers with many safe defaults.
109
+ test_files: []