From 869e8a6667568680a118cef0aa9bd68cd8623aa1 Mon Sep 17 00:00:00 2001 From: arashnd Date: Thu, 31 Oct 2024 03:03:14 +0500 Subject: [PATCH 1/3] Lowercase headers --- CHANGELOG.md | 16 ++--- README.md | 20 +++--- docs/hashes.md | 2 +- docs/per_action_configuration.md | 6 +- docs/upgrading-to-4-0.md | 2 +- lib/secure_headers/configuration.rb | 2 +- lib/secure_headers/headers/clear_site_data.rb | 8 +-- .../headers/content_security_policy.rb | 4 +- .../headers/content_security_policy_config.rb | 4 +- .../expect_certificate_transparency.rb | 4 +- .../headers/policy_management.rb | 4 +- lib/secure_headers/headers/referrer_policy.rb | 2 +- .../headers/strict_transport_security.rb | 2 +- .../headers/x_content_type_options.rb | 2 +- .../headers/x_download_options.rb | 4 +- lib/secure_headers/headers/x_frame_options.rb | 2 +- .../x_permitted_cross_domain_policies.rb | 4 +- .../headers/x_xss_protection.rb | 2 +- lib/secure_headers/railtie.rb | 8 +-- spec/lib/secure_headers_spec.rb | 68 +++++++++---------- 20 files changed, 83 insertions(+), 83 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 662bdd1a..18147749 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,11 +62,11 @@ NOTE: this version is a breaking change due to the removal of HPKP. Remove the H ## 5.0.2 -- Updates `Referrer-Policy` header to support multiple policy values +- Updates `referrer-policy` header to support multiple policy values ## 5.0.1 -- Updates `Expect-CT` header to use a comma separator between directives, as specified in the most current spec. +- Updates `expect-ct` header to use a comma separator between directives, as specified in the most current spec. ## 5.0.0 @@ -90,7 +90,7 @@ Fix support for the sandbox attribute of CSP. `true` and `[]` represent the maxi ## 3.7.0 -Adds support for the `Expect-CT` header (@jacobbednarz: https://github.com/twitter/secureheaders/pull/322) +Adds support for the `expect-ct` header (@jacobbednarz: https://github.com/twitter/secureheaders/pull/322) ## 3.6.7 @@ -335,7 +335,7 @@ console.log(1) ``` ``` -Content-Security-Policy: ... +content-security-policy: ... script-src 'sha256-yktKiAsZWmc8WpOyhnmhQoDf9G2dAZvuBBC+V0LGQhg=' ... ; style-src 'sha256-SLp6LO3rrKDJwsG9uJUxZapb4Wp2Zhj6Bu3l+d9rnAY=' 'sha256-HSGHqlRoKmHAGTAJ2Rq0piXX4CnEbOl1ArNd6ejp2TE=' ...; ``` @@ -552,15 +552,15 @@ Fixes an issue where view helpers (for nonces, hashes, etc) weren't available in This release contains support for more csp level 2 features such as the new directives, the script hash integration, and more. -It also sets a new header by default: `X-Permitted-Cross-Domain-Policies` +It also sets a new header by default: `x-permitted-cross-domain-policies` Support for hpkp is not included in this release as the implementations are still very unstable. :rocket: -## v.2.0.0.pre2 - 2014-12-06 01:55:42 UTC - Adds X-Permitted-Cross-Domain-Policies support by default +## v.2.0.0.pre2 - 2014-12-06 01:55:42 UTC - Adds x-permitted-cross-domain-policies support by default -The only change between this and the first pre release is that the X-Permitted-Cross-Domain-Policies support is included. +The only change between this and the first pre release is that the x-permitted-cross-domain-policies support is included. ## v1.4.0 - 2014-12-06 01:54:48 UTC - Deprecate features in preparation for 2.0 @@ -572,7 +572,7 @@ This release is intended to be ready for CSP level 2. Mainly, this means there i ## v1.3.4 - 2014-10-13 22:05:44 UTC - -* Adds X-Download-Options support +* Adds x-download-options support * Adds support for X-XSS-Protection reporting * Defers loading of rails engine for faster boot times diff --git a/README.md b/README.md index 1683c84f..ae76dc1e 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,11 @@ The gem will automatically apply several headers that are related to security. - X-Frame-Options (XFO) - Prevents your content from being framed and potentially clickjacked. [X-Frame-Options Specification](https://tools.ietf.org/html/rfc7034) - X-XSS-Protection - [Cross site scripting heuristic filter for IE/Chrome](https://msdn.microsoft.com/en-us/library/dd565647\(v=vs.85\).aspx) - X-Content-Type-Options - [Prevent content type sniffing](https://msdn.microsoft.com/library/gg622941\(v=vs.85\).aspx) -- X-Download-Options - [Prevent file downloads opening](https://msdn.microsoft.com/library/jj542450(v=vs.85).aspx) -- X-Permitted-Cross-Domain-Policies - [Restrict Adobe Flash Player's access to data](https://www.adobe.com/devnet/adobe-media-server/articles/cross-domain-xml-for-streaming.html) -- Referrer-Policy - [Referrer Policy draft](https://w3c.github.io/webappsec-referrer-policy/) -- Expect-CT - Only use certificates that are present in the certificate transparency logs. [Expect-CT draft specification](https://datatracker.ietf.org/doc/draft-stark-expect-ct/). -- Clear-Site-Data - Clearing browser data for origin. [Clear-Site-Data specification](https://w3c.github.io/webappsec-clear-site-data/). +- x-download-options - [Prevent file downloads opening](https://msdn.microsoft.com/library/jj542450(v=vs.85).aspx) +- x-permitted-cross-domain-policies - [Restrict Adobe Flash Player's access to data](https://www.adobe.com/devnet/adobe-media-server/articles/cross-domain-xml-for-streaming.html) +- referrer-policy - [Referrer Policy draft](https://w3c.github.io/webappsec-referrer-policy/) +- expect-ct - Only use certificates that are present in the certificate transparency logs. [expect-ct draft specification](https://datatracker.ietf.org/doc/draft-stark-expect-ct/). +- clear-site-data - Clearing browser data for origin. [clear-site-data specification](https://w3c.github.io/webappsec-clear-site-data/). It can also mark all http cookies with the Secure, HttpOnly and SameSite attributes. This is on default but can be turned off by using `config.cookies = SecureHeaders::OPT_OUT`. @@ -92,19 +92,19 @@ end ``` ### Deprecated Configuration Values -* `block_all_mixed_content` - this value is deprecated in favor of `upgrade_insecure_requests`. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/block-all-mixed-content for more information. +* `block_all_mixed_content` - this value is deprecated in favor of `upgrade_insecure_requests`. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/content-security-policy/block-all-mixed-content for more information. ## Default values All headers except for PublicKeyPins and ClearSiteData have a default value. The default set of headers is: ``` -Content-Security-Policy: default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline' -Strict-Transport-Security: max-age=631138519 +content-security-policy: default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline' +strict-transport-security: max-age=631138519 X-Content-Type-Options: nosniff -X-Download-Options: noopen +x-download-options: noopen X-Frame-Options: sameorigin -X-Permitted-Cross-Domain-Policies: none +x-permitted-cross-domain-policies: none X-Xss-Protection: 0 ``` diff --git a/docs/hashes.md b/docs/hashes.md index 752d42a5..ae6af984 100644 --- a/docs/hashes.md +++ b/docs/hashes.md @@ -58,7 +58,7 @@ console.log(1) ``` ``` -Content-Security-Policy: ... +content-security-policy: ... script-src 'sha256-yktKiAsZWmc8WpOyhnmhQoDf9G2dAZvuBBC+V0LGQhg=' ... ; style-src 'sha256-SLp6LO3rrKDJwsG9uJUxZapb4Wp2Zhj6Bu3l+d9rnAY=' 'sha256-HSGHqlRoKmHAGTAJ2Rq0piXX4CnEbOl1ArNd6ejp2TE=' ...; ``` diff --git a/docs/per_action_configuration.md b/docs/per_action_configuration.md index 63716dba..fda5d59a 100644 --- a/docs/per_action_configuration.md +++ b/docs/per_action_configuration.md @@ -91,7 +91,7 @@ body { ``` -Content-Security-Policy: ... +content-security-policy: ... script-src 'nonce-/jRAxuLJsDXAxqhNBB7gg7h55KETtDQBXe4ZL+xIXwI=' ...; style-src 'nonce-/jRAxuLJsDXAxqhNBB7gg7h55KETtDQBXe4ZL+xIXwI=' ...; ``` @@ -118,13 +118,13 @@ You can clear the browser cache after the logout request by using the following. ``` ruby class ApplicationController < ActionController::Base - # Configuration override to send the Clear-Site-Data header. + # Configuration override to send the clear-site-data header. SecureHeaders::Configuration.override(:clear_browser_cache) do |config| config.clear_site_data = SecureHeaders::ClearSiteData::ALL_TYPES end - # Clears the browser's cache for browsers supporting the Clear-Site-Data + # Clears the browser's cache for browsers supporting the clear-site-data # header. # # Returns nothing. diff --git a/docs/upgrading-to-4-0.md b/docs/upgrading-to-4-0.md index f9d6a2bb..15da15af 100644 --- a/docs/upgrading-to-4-0.md +++ b/docs/upgrading-to-4-0.md @@ -15,7 +15,7 @@ The default CSP has changed to be more universal without sacrificing too much se Previously, the default CSP was: -`Content-Security-Policy: default-src 'self'` +`content-security-policy: default-src 'self'` The new default policy is: diff --git a/lib/secure_headers/configuration.rb b/lib/secure_headers/configuration.rb index 2ebbf487..e96f4f9d 100644 --- a/lib/secure_headers/configuration.rb +++ b/lib/secure_headers/configuration.rb @@ -256,7 +256,7 @@ def csp=(new_csp) end end - # Configures the Content-Security-Policy-Report-Only header. `new_csp` cannot + # Configures the content-security-policy-report-only header. `new_csp` cannot # contain `report_only: false` or an error will be raised. # # NOTE: if csp has not been configured/has the default value when diff --git a/lib/secure_headers/headers/clear_site_data.rb b/lib/secure_headers/headers/clear_site_data.rb index bf8078d4..0fdc0c2a 100644 --- a/lib/secure_headers/headers/clear_site_data.rb +++ b/lib/secure_headers/headers/clear_site_data.rb @@ -2,7 +2,7 @@ module SecureHeaders class ClearSiteDataConfigError < StandardError; end class ClearSiteData - HEADER_NAME = "Clear-Site-Data".freeze + HEADER_NAME = "clear-site-data".freeze # Valid `types` CACHE = "cache".freeze @@ -12,7 +12,7 @@ class ClearSiteData ALL_TYPES = [CACHE, COOKIES, STORAGE, EXECUTION_CONTEXTS] class << self - # Public: make an Clear-Site-Data header name, value pair + # Public: make an clear-site-data header name, value pair # # Returns nil if not configured, returns header name and value if configured. def make_header(config = nil, user_agent = nil) @@ -39,8 +39,8 @@ def validate_config!(config) end end - # Public: Transform a Clear-Site-Data config (an Array of Strings) into a - # String that can be used as the value for the Clear-Site-Data header. + # Public: Transform a clear-site-data config (an Array of Strings) into a + # String that can be used as the value for the clear-site-data header. # # types - An Array of String of types of data to clear. # diff --git a/lib/secure_headers/headers/content_security_policy.rb b/lib/secure_headers/headers/content_security_policy.rb index 4a7b0d76..ae225e7c 100644 --- a/lib/secure_headers/headers/content_security_policy.rb +++ b/lib/secure_headers/headers/content_security_policy.rb @@ -26,8 +26,8 @@ def initialize(config = nil) end ## - # Returns the name to use for the header. Either "Content-Security-Policy" or - # "Content-Security-Policy-Report-Only" + # Returns the name to use for the header. Either "content-security-policy" or + # "content-security-policy-report-only" def name @config.class.const_get(:HEADER_NAME) end diff --git a/lib/secure_headers/headers/content_security_policy_config.rb b/lib/secure_headers/headers/content_security_policy_config.rb index 50ca6bd4..1786b3fa 100644 --- a/lib/secure_headers/headers/content_security_policy_config.rb +++ b/lib/secure_headers/headers/content_security_policy_config.rb @@ -78,7 +78,7 @@ def write_attribute(attr, value) class ContentSecurityPolicyConfigError < StandardError; end class ContentSecurityPolicyConfig - HEADER_NAME = "Content-Security-Policy".freeze + HEADER_NAME = "content-security-policy".freeze ATTRS = Set.new(PolicyManagement::ALL_DIRECTIVES + PolicyManagement::META_CONFIGS + PolicyManagement::NONCES) def self.attrs @@ -107,7 +107,7 @@ def make_report_only end class ContentSecurityPolicyReportOnlyConfig < ContentSecurityPolicyConfig - HEADER_NAME = "Content-Security-Policy-Report-Only".freeze + HEADER_NAME = "content-security-policy-report-only".freeze def report_only? true diff --git a/lib/secure_headers/headers/expect_certificate_transparency.rb b/lib/secure_headers/headers/expect_certificate_transparency.rb index b65cbd09..4b7272dd 100644 --- a/lib/secure_headers/headers/expect_certificate_transparency.rb +++ b/lib/secure_headers/headers/expect_certificate_transparency.rb @@ -3,14 +3,14 @@ module SecureHeaders class ExpectCertificateTransparencyConfigError < StandardError; end class ExpectCertificateTransparency - HEADER_NAME = "Expect-CT".freeze + HEADER_NAME = "expect-ct".freeze INVALID_CONFIGURATION_ERROR = "config must be a hash.".freeze INVALID_ENFORCE_VALUE_ERROR = "enforce must be a boolean".freeze REQUIRED_MAX_AGE_ERROR = "max-age is a required directive.".freeze INVALID_MAX_AGE_ERROR = "max-age must be a number.".freeze class << self - # Public: Generate a Expect-CT header. + # Public: Generate a expect-ct header. # # Returns nil if not configured, returns header name and value if # configured. diff --git a/lib/secure_headers/headers/policy_management.rb b/lib/secure_headers/headers/policy_management.rb index 668e79a5..3129c0d3 100644 --- a/lib/secure_headers/headers/policy_management.rb +++ b/lib/secure_headers/headers/policy_management.rb @@ -98,9 +98,9 @@ def self.included(base) # Experimental directives - these vary greatly in support # See MDN for details. - # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/trusted-types + # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/content-security-policy/trusted-types TRUSTED_TYPES = :trusted_types - # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/require-trusted-types-for + # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/content-security-policy/require-trusted-types-for REQUIRE_TRUSTED_TYPES_FOR = :require_trusted_types_for DIRECTIVES_EXPERIMENTAL = [ diff --git a/lib/secure_headers/headers/referrer_policy.rb b/lib/secure_headers/headers/referrer_policy.rb index c18188f8..a4589117 100644 --- a/lib/secure_headers/headers/referrer_policy.rb +++ b/lib/secure_headers/headers/referrer_policy.rb @@ -2,7 +2,7 @@ module SecureHeaders class ReferrerPolicyConfigError < StandardError; end class ReferrerPolicy - HEADER_NAME = "Referrer-Policy".freeze + HEADER_NAME = "referrer-policy".freeze DEFAULT_VALUE = "origin-when-cross-origin" VALID_POLICIES = %w( no-referrer diff --git a/lib/secure_headers/headers/strict_transport_security.rb b/lib/secure_headers/headers/strict_transport_security.rb index 36df032c..3d78a484 100644 --- a/lib/secure_headers/headers/strict_transport_security.rb +++ b/lib/secure_headers/headers/strict_transport_security.rb @@ -3,7 +3,7 @@ module SecureHeaders class STSConfigError < StandardError; end class StrictTransportSecurity - HEADER_NAME = "Strict-Transport-Security".freeze + HEADER_NAME = "strict-transport-security".freeze HSTS_MAX_AGE = "631138519" DEFAULT_VALUE = "max-age=" + HSTS_MAX_AGE VALID_STS_HEADER = /\Amax-age=\d+(; includeSubdomains)?(; preload)?\z/i diff --git a/lib/secure_headers/headers/x_content_type_options.rb b/lib/secure_headers/headers/x_content_type_options.rb index cf4371f5..96f8d314 100644 --- a/lib/secure_headers/headers/x_content_type_options.rb +++ b/lib/secure_headers/headers/x_content_type_options.rb @@ -3,7 +3,7 @@ module SecureHeaders class XContentTypeOptionsConfigError < StandardError; end class XContentTypeOptions - HEADER_NAME = "X-Content-Type-Options".freeze + HEADER_NAME = "x-content-type-options".freeze DEFAULT_VALUE = "nosniff" class << self diff --git a/lib/secure_headers/headers/x_download_options.rb b/lib/secure_headers/headers/x_download_options.rb index db327dca..1eb1356a 100644 --- a/lib/secure_headers/headers/x_download_options.rb +++ b/lib/secure_headers/headers/x_download_options.rb @@ -2,11 +2,11 @@ module SecureHeaders class XDOConfigError < StandardError; end class XDownloadOptions - HEADER_NAME = "X-Download-Options".freeze + HEADER_NAME = "x-download-options".freeze DEFAULT_VALUE = "noopen" class << self - # Public: generate an X-Download-Options header. + # Public: generate an x-download-options header. # # Returns a default header if no configuration is provided, or a # header name and value based on the config. diff --git a/lib/secure_headers/headers/x_frame_options.rb b/lib/secure_headers/headers/x_frame_options.rb index 508ae364..636e3bfa 100644 --- a/lib/secure_headers/headers/x_frame_options.rb +++ b/lib/secure_headers/headers/x_frame_options.rb @@ -2,7 +2,7 @@ module SecureHeaders class XFOConfigError < StandardError; end class XFrameOptions - HEADER_NAME = "X-Frame-Options".freeze + HEADER_NAME = "x-frame-options".freeze SAMEORIGIN = "sameorigin" DENY = "deny" ALLOW_FROM = "allow-from" diff --git a/lib/secure_headers/headers/x_permitted_cross_domain_policies.rb b/lib/secure_headers/headers/x_permitted_cross_domain_policies.rb index 416c9f01..a34dd58f 100644 --- a/lib/secure_headers/headers/x_permitted_cross_domain_policies.rb +++ b/lib/secure_headers/headers/x_permitted_cross_domain_policies.rb @@ -2,12 +2,12 @@ module SecureHeaders class XPCDPConfigError < StandardError; end class XPermittedCrossDomainPolicies - HEADER_NAME = "X-Permitted-Cross-Domain-Policies".freeze + HEADER_NAME = "x-permitted-cross-domain-policies".freeze DEFAULT_VALUE = "none" VALID_POLICIES = %w(all none master-only by-content-type by-ftp-filename) class << self - # Public: generate an X-Permitted-Cross-Domain-Policies header. + # Public: generate an x-permitted-cross-domain-policies header. # # Returns a default header if no configuration is provided, or a # header name and value based on the config. diff --git a/lib/secure_headers/headers/x_xss_protection.rb b/lib/secure_headers/headers/x_xss_protection.rb index 5be385de..bd5b7faa 100644 --- a/lib/secure_headers/headers/x_xss_protection.rb +++ b/lib/secure_headers/headers/x_xss_protection.rb @@ -2,7 +2,7 @@ module SecureHeaders class XXssProtectionConfigError < StandardError; end class XXssProtection - HEADER_NAME = "X-XSS-Protection".freeze + HEADER_NAME = "x-xss-protection".freeze DEFAULT_VALUE = "0".freeze VALID_X_XSS_HEADER = /\A[01](; mode=block)?(; report=.*)?\z/ diff --git a/lib/secure_headers/railtie.rb b/lib/secure_headers/railtie.rb index 53c3aec6..b701a472 100644 --- a/lib/secure_headers/railtie.rb +++ b/lib/secure_headers/railtie.rb @@ -5,10 +5,10 @@ module SecureHeaders class Railtie < Rails::Railtie isolate_namespace SecureHeaders if defined? isolate_namespace # rails 3.0 conflicting_headers = ["X-Frame-Options", "X-XSS-Protection", - "X-Permitted-Cross-Domain-Policies", "X-Download-Options", - "X-Content-Type-Options", "Strict-Transport-Security", - "Content-Security-Policy", "Content-Security-Policy-Report-Only", - "Public-Key-Pins", "Public-Key-Pins-Report-Only", "Referrer-Policy"] + "x-permitted-cross-domain-policies", "x-download-options", + "X-Content-Type-Options", "strict-transport-security", + "content-security-policy", "content-security-policy-report-only", + "Public-Key-Pins", "Public-Key-Pins-Report-Only", "referrer-policy"] initializer "secure_headers.middleware" do Rails.application.config.middleware.insert_before 0, SecureHeaders::Middleware diff --git a/spec/lib/secure_headers_spec.rb b/spec/lib/secure_headers_spec.rb index be608c74..0003c5c0 100644 --- a/spec/lib/secure_headers_spec.rb +++ b/spec/lib/secure_headers_spec.rb @@ -45,9 +45,9 @@ module SecureHeaders SecureHeaders.opt_out_of_header(request, :csp_report_only) SecureHeaders.opt_out_of_header(request, :x_content_type_options) hash = SecureHeaders.header_hash_for(request) - expect(hash["Content-Security-Policy-Report-Only"]).to be_nil - expect(hash["Content-Security-Policy"]).to be_nil - expect(hash["X-Content-Type-Options"]).to be_nil + expect(hash["content-security-policy-report-only"]).to be_nil + expect(hash["content-security-policy"]).to be_nil + expect(hash["x-content-type-options"]).to be_nil end it "Carries options over when using overrides" do @@ -62,9 +62,9 @@ module SecureHeaders SecureHeaders.use_secure_headers_override(request, :api) hash = SecureHeaders.header_hash_for(request) - expect(hash["X-Download-Options"]).to be_nil - expect(hash["X-Permitted-Cross-Domain-Policies"]).to be_nil - expect(hash["X-Frame-Options"]).to be_nil + expect(hash["x-download-options"]).to be_nil + expect(hash["x-permitted-cross-domain-policies"]).to be_nil + expect(hash["x-frame-options"]).to be_nil end it "Overrides the current default config if default config changes during request" do @@ -81,8 +81,8 @@ module SecureHeaders SecureHeaders.use_secure_headers_override(request, :dynamic_override) hash = SecureHeaders.header_hash_for(request) - expect(hash["X-Content-Type-Options"]).to eq("nosniff") - expect(hash["X-Frame-Options"]).to eq("DENY") + expect(hash["x-content-type-options"]).to eq("nosniff") + expect(hash["x-frame-options"]).to eq("DENY") end it "allows you to opt out entirely" do @@ -96,7 +96,7 @@ module SecureHeaders expect(hash.count).to eq(0) end - it "allows you to override X-Frame-Options settings" do + it "allows you to override x-frame-options settings" do Configuration.default SecureHeaders.override_x_frame_options(request, XFrameOptions::DENY) hash = SecureHeaders.header_hash_for(request) @@ -240,7 +240,7 @@ module SecureHeaders SecureHeaders.content_security_policy_script_nonce(chrome_request) hash = SecureHeaders.header_hash_for(chrome_request) - expect(hash["Content-Security-Policy"]).to eq("default-src 'self'; script-src mycdn.com 'nonce-#{nonce}' 'unsafe-inline'; style-src 'self'") + expect(hash["content-security-policy"]).to eq("default-src 'self'; script-src mycdn.com 'nonce-#{nonce}' 'unsafe-inline'; style-src 'self'") end it "does not support the deprecated `report_only: true` format" do @@ -291,8 +291,8 @@ module SecureHeaders end hash = SecureHeaders.header_hash_for(request) - expect(hash["Content-Security-Policy"]).to eq("default-src 'self'; script-src 'self'") - expect(hash["Content-Security-Policy-Report-Only"]).to eq("default-src 'self'; script-src 'self'") + expect(hash["content-security-policy"]).to eq("default-src 'self'; script-src 'self'") + expect(hash["content-security-policy-report-only"]).to eq("default-src 'self'; script-src 'self'") end it "sets different headers when the configs are different" do @@ -306,8 +306,8 @@ module SecureHeaders end hash = SecureHeaders.header_hash_for(request) - expect(hash["Content-Security-Policy"]).to eq("default-src 'self'; script-src 'self'") - expect(hash["Content-Security-Policy-Report-Only"]).to eq("default-src 'self'; script-src foo.com") + expect(hash["content-security-policy"]).to eq("default-src 'self'; script-src 'self'") + expect(hash["content-security-policy-report-only"]).to eq("default-src 'self'; script-src foo.com") end it "allows you to opt-out of enforced CSP" do @@ -321,50 +321,50 @@ module SecureHeaders end hash = SecureHeaders.header_hash_for(request) - expect(hash["Content-Security-Policy"]).to be_nil - expect(hash["Content-Security-Policy-Report-Only"]).to eq("default-src 'self'; script-src 'self'") + expect(hash["content-security-policy"]).to be_nil + expect(hash["content-security-policy-report-only"]).to eq("default-src 'self'; script-src 'self'") end it "allows appending to the enforced policy" do SecureHeaders.append_content_security_policy_directives(request, {script_src: %w(anothercdn.com)}, :enforced) hash = SecureHeaders.header_hash_for(request) - expect(hash["Content-Security-Policy"]).to eq("default-src 'self'; script-src 'self' anothercdn.com") - expect(hash["Content-Security-Policy-Report-Only"]).to eq("default-src 'self'; script-src 'self'") + expect(hash["content-security-policy"]).to eq("default-src 'self'; script-src 'self' anothercdn.com") + expect(hash["content-security-policy-report-only"]).to eq("default-src 'self'; script-src 'self'") end it "allows appending to the report only policy" do SecureHeaders.append_content_security_policy_directives(request, {script_src: %w(anothercdn.com)}, :report_only) hash = SecureHeaders.header_hash_for(request) - expect(hash["Content-Security-Policy"]).to eq("default-src 'self'; script-src 'self'") - expect(hash["Content-Security-Policy-Report-Only"]).to eq("default-src 'self'; script-src 'self' anothercdn.com") + expect(hash["content-security-policy"]).to eq("default-src 'self'; script-src 'self'") + expect(hash["content-security-policy-report-only"]).to eq("default-src 'self'; script-src 'self' anothercdn.com") end it "allows appending to both policies" do SecureHeaders.append_content_security_policy_directives(request, {script_src: %w(anothercdn.com)}, :both) hash = SecureHeaders.header_hash_for(request) - expect(hash["Content-Security-Policy"]).to eq("default-src 'self'; script-src 'self' anothercdn.com") - expect(hash["Content-Security-Policy-Report-Only"]).to eq("default-src 'self'; script-src 'self' anothercdn.com") + expect(hash["content-security-policy"]).to eq("default-src 'self'; script-src 'self' anothercdn.com") + expect(hash["content-security-policy-report-only"]).to eq("default-src 'self'; script-src 'self' anothercdn.com") end it "allows overriding the enforced policy" do SecureHeaders.override_content_security_policy_directives(request, {script_src: %w(anothercdn.com)}, :enforced) hash = SecureHeaders.header_hash_for(request) - expect(hash["Content-Security-Policy"]).to eq("default-src 'self'; script-src anothercdn.com") - expect(hash["Content-Security-Policy-Report-Only"]).to eq("default-src 'self'; script-src 'self'") + expect(hash["content-security-policy"]).to eq("default-src 'self'; script-src anothercdn.com") + expect(hash["content-security-policy-report-only"]).to eq("default-src 'self'; script-src 'self'") end it "allows overriding the report only policy" do SecureHeaders.override_content_security_policy_directives(request, {script_src: %w(anothercdn.com)}, :report_only) hash = SecureHeaders.header_hash_for(request) - expect(hash["Content-Security-Policy"]).to eq("default-src 'self'; script-src 'self'") - expect(hash["Content-Security-Policy-Report-Only"]).to eq("default-src 'self'; script-src anothercdn.com") + expect(hash["content-security-policy"]).to eq("default-src 'self'; script-src 'self'") + expect(hash["content-security-policy-report-only"]).to eq("default-src 'self'; script-src anothercdn.com") end it "allows overriding both policies" do SecureHeaders.override_content_security_policy_directives(request, {script_src: %w(anothercdn.com)}, :both) hash = SecureHeaders.header_hash_for(request) - expect(hash["Content-Security-Policy"]).to eq("default-src 'self'; script-src anothercdn.com") - expect(hash["Content-Security-Policy-Report-Only"]).to eq("default-src 'self'; script-src anothercdn.com") + expect(hash["content-security-policy"]).to eq("default-src 'self'; script-src anothercdn.com") + expect(hash["content-security-policy-report-only"]).to eq("default-src 'self'; script-src anothercdn.com") end context "when inferring which config to modify" do @@ -379,8 +379,8 @@ module SecureHeaders SecureHeaders.append_content_security_policy_directives(request, {script_src: %w(anothercdn.com)}) hash = SecureHeaders.header_hash_for(request) - expect(hash["Content-Security-Policy"]).to eq("default-src 'self'; script-src 'self' anothercdn.com") - expect(hash["Content-Security-Policy-Report-Only"]).to be_nil + expect(hash["content-security-policy"]).to eq("default-src 'self'; script-src 'self' anothercdn.com") + expect(hash["content-security-policy-report-only"]).to be_nil end it "updates the report only header when configured" do @@ -395,8 +395,8 @@ module SecureHeaders SecureHeaders.append_content_security_policy_directives(request, {script_src: %w(anothercdn.com)}) hash = SecureHeaders.header_hash_for(request) - expect(hash["Content-Security-Policy-Report-Only"]).to eq("default-src 'self'; script-src 'self' anothercdn.com") - expect(hash["Content-Security-Policy"]).to be_nil + expect(hash["content-security-policy-report-only"]).to eq("default-src 'self'; script-src 'self' anothercdn.com") + expect(hash["content-security-policy"]).to be_nil end it "updates both headers if both are configured" do @@ -414,8 +414,8 @@ module SecureHeaders SecureHeaders.append_content_security_policy_directives(request, {script_src: %w(anothercdn.com)}) hash = SecureHeaders.header_hash_for(request) - expect(hash["Content-Security-Policy"]).to eq("default-src enforced.com; script-src 'self' anothercdn.com") - expect(hash["Content-Security-Policy-Report-Only"]).to eq("default-src reportonly.com; script-src 'self' anothercdn.com") + expect(hash["content-security-policy"]).to eq("default-src enforced.com; script-src 'self' anothercdn.com") + expect(hash["content-security-policy-report-only"]).to eq("default-src reportonly.com; script-src 'self' anothercdn.com") end end From 399706f668109bd4b01afe06b849208eab116343 Mon Sep 17 00:00:00 2001 From: Rahul Zhade Date: Thu, 5 Dec 2024 20:43:37 -0500 Subject: [PATCH 2/3] Apply suggestions from code review --- README.md | 8 ++++---- lib/secure_headers/railtie.rb | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index ae76dc1e..643e3b6f 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,7 @@ end ``` ### Deprecated Configuration Values -* `block_all_mixed_content` - this value is deprecated in favor of `upgrade_insecure_requests`. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/content-security-policy/block-all-mixed-content for more information. +* `block_all_mixed_content` - this value is deprecated in favor of `upgrade_insecure_requests`. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/block-all-mixed-content for more information. ## Default values @@ -101,11 +101,11 @@ All headers except for PublicKeyPins and ClearSiteData have a default value. The ``` content-security-policy: default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline' strict-transport-security: max-age=631138519 -X-Content-Type-Options: nosniff +x-content-type-options: nosniff x-download-options: noopen -X-Frame-Options: sameorigin +x-frame-options: sameorigin x-permitted-cross-domain-policies: none -X-Xss-Protection: 0 +x-xss-protection: 0 ``` ## API configurations diff --git a/lib/secure_headers/railtie.rb b/lib/secure_headers/railtie.rb index b701a472..ba255acc 100644 --- a/lib/secure_headers/railtie.rb +++ b/lib/secure_headers/railtie.rb @@ -4,11 +4,11 @@ module SecureHeaders class Railtie < Rails::Railtie isolate_namespace SecureHeaders if defined? isolate_namespace # rails 3.0 - conflicting_headers = ["X-Frame-Options", "X-XSS-Protection", + conflicting_headers = ["x-frame-options", "x-xss-protection", "x-permitted-cross-domain-policies", "x-download-options", - "X-Content-Type-Options", "strict-transport-security", + "x-content-type-options", "strict-transport-security", "content-security-policy", "content-security-policy-report-only", - "Public-Key-Pins", "Public-Key-Pins-Report-Only", "referrer-policy"] + "public-key-pins", "public-key-pins-report-only", "referrer-policy"] initializer "secure_headers.middleware" do Rails.application.config.middleware.insert_before 0, SecureHeaders::Middleware From abbaf1d3c40c35e3964db2530c296f479706d03f Mon Sep 17 00:00:00 2001 From: Rahul Zhade Date: Thu, 5 Dec 2024 20:46:31 -0500 Subject: [PATCH 3/3] Revert Changelog --- CHANGELOG.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18147749..3112d5cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,11 +62,11 @@ NOTE: this version is a breaking change due to the removal of HPKP. Remove the H ## 5.0.2 -- Updates `referrer-policy` header to support multiple policy values +- Updates `Referrer-Policy` header to support multiple policy values ## 5.0.1 -- Updates `expect-ct` header to use a comma separator between directives, as specified in the most current spec. +- Updates `Expect-CT` header to use a comma separator between directives, as specified in the most current spec. ## 5.0.0 @@ -90,7 +90,7 @@ Fix support for the sandbox attribute of CSP. `true` and `[]` represent the maxi ## 3.7.0 -Adds support for the `expect-ct` header (@jacobbednarz: https://github.com/twitter/secureheaders/pull/322) +Adds support for the `Expect-CT` header (@jacobbednarz: https://github.com/twitter/secureheaders/pull/322) ## 3.6.7 @@ -335,7 +335,7 @@ console.log(1) ``` ``` -content-security-policy: ... +Content-Security-Policy: ... script-src 'sha256-yktKiAsZWmc8WpOyhnmhQoDf9G2dAZvuBBC+V0LGQhg=' ... ; style-src 'sha256-SLp6LO3rrKDJwsG9uJUxZapb4Wp2Zhj6Bu3l+d9rnAY=' 'sha256-HSGHqlRoKmHAGTAJ2Rq0piXX4CnEbOl1ArNd6ejp2TE=' ...; ``` @@ -552,15 +552,15 @@ Fixes an issue where view helpers (for nonces, hashes, etc) weren't available in This release contains support for more csp level 2 features such as the new directives, the script hash integration, and more. -It also sets a new header by default: `x-permitted-cross-domain-policies` +It also sets a new header by default: `X-Permitted-Cross-Domain-Policies` Support for hpkp is not included in this release as the implementations are still very unstable. :rocket: -## v.2.0.0.pre2 - 2014-12-06 01:55:42 UTC - Adds x-permitted-cross-domain-policies support by default +## v.2.0.0.pre2 - 2014-12-06 01:55:42 UTC - Adds X-Permitted-Cross-Domain-Policies support by default -The only change between this and the first pre release is that the x-permitted-cross-domain-policies support is included. +The only change between this and the first pre release is that the X-Permitted-Cross-Domain-Policies support is included. ## v1.4.0 - 2014-12-06 01:54:48 UTC - Deprecate features in preparation for 2.0 @@ -572,7 +572,7 @@ This release is intended to be ready for CSP level 2. Mainly, this means there i ## v1.3.4 - 2014-10-13 22:05:44 UTC - -* Adds x-download-options support +* Adds X-Download-Options support * Adds support for X-XSS-Protection reporting * Defers loading of rails engine for faster boot times @@ -598,4 +598,4 @@ It's often valuable to send extra information in the report uri that is not avai Results in ``` report-uri csp_reports?enforce=true&app_name=twitter -``` +``` \ No newline at end of file