diff --git a/.rubocop.yml b/.rubocop.yml index 938b22da..6548e1a3 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,4 +1,5 @@ inherit_gem: rubocop-github: - config/default.yml -require: rubocop-performance +plugins: + - rubocop-performance diff --git a/lib/secure_headers.rb b/lib/secure_headers.rb index 6426e538..4b288c8e 100644 --- a/lib/secure_headers.rb +++ b/lib/secure_headers.rb @@ -208,7 +208,7 @@ def raise_on_unknown_target(target) def config_and_target(request, target) config = config_for(request) - target = guess_target(config) unless target + target ||= guess_target(config) raise_on_unknown_target(target) [config, target] end diff --git a/lib/secure_headers/headers/clear_site_data.rb b/lib/secure_headers/headers/clear_site_data.rb index 0fdc0c2a..05d26a8f 100644 --- a/lib/secure_headers/headers/clear_site_data.rb +++ b/lib/secure_headers/headers/clear_site_data.rb @@ -11,43 +11,41 @@ class ClearSiteData EXECUTION_CONTEXTS = "executionContexts".freeze ALL_TYPES = [CACHE, COOKIES, STORAGE, EXECUTION_CONTEXTS] - class << self - # 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) - case config - when nil, OPT_OUT, [] - # noop - when Array - [HEADER_NAME, make_header_value(config)] - when true - [HEADER_NAME, make_header_value(ALL_TYPES)] - end + # Public: make an clear-site-data header name, value pair + # + # Returns nil if not configured, returns header name and value if configured. + def self.make_header(config = nil, user_agent = nil) + case config + when nil, OPT_OUT, [] + # noop + when Array + [HEADER_NAME, make_header_value(config)] + when true + [HEADER_NAME, make_header_value(ALL_TYPES)] end + end - def validate_config!(config) - case config - when nil, OPT_OUT, true - # valid - when Array - unless config.all? { |t| t.is_a?(String) } - raise ClearSiteDataConfigError.new("types must be Strings") - end - else - raise ClearSiteDataConfigError.new("config must be an Array of Strings or `true`") + def self.validate_config!(config) + case config + when nil, OPT_OUT, true + # valid + when Array + unless config.all? { |t| t.is_a?(String) } + raise ClearSiteDataConfigError.new("types must be Strings") end + else + raise ClearSiteDataConfigError.new("config must be an Array of Strings or `true`") 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. - # - # types - An Array of String of types of data to clear. - # - # Returns a String of quoted values that are comma separated. - def make_header_value(types) - types.map { |t| %("#{t}") }.join(", ") - 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. + # + # types - An Array of String of types of data to clear. + # + # Returns a String of quoted values that are comma separated. + def self.make_header_value(types) + types.map { |t| %("#{t}") }.join(", ") end end end diff --git a/lib/secure_headers/headers/cookie.rb b/lib/secure_headers/headers/cookie.rb index 9d3f7cd1..8f78612c 100644 --- a/lib/secure_headers/headers/cookie.rb +++ b/lib/secure_headers/headers/cookie.rb @@ -7,10 +7,8 @@ module SecureHeaders class CookiesConfigError < StandardError; end class Cookie - class << self - def validate_config!(config) - CookiesConfig.new(config).validate! - end + def self.validate_config!(config) + CookiesConfig.new(config).validate! end attr_reader :raw_cookie, :config diff --git a/lib/secure_headers/headers/expect_certificate_transparency.rb b/lib/secure_headers/headers/expect_certificate_transparency.rb index 4b7272dd..582e8a05 100644 --- a/lib/secure_headers/headers/expect_certificate_transparency.rb +++ b/lib/secure_headers/headers/expect_certificate_transparency.rb @@ -9,31 +9,29 @@ class ExpectCertificateTransparency 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. - # - # Returns nil if not configured, returns header name and value if - # configured. - def make_header(config, use_agent = nil) - return if config.nil? || config == OPT_OUT + # Public: Generate a expect-ct header. + # + # Returns nil if not configured, returns header name and value if + # configured. + def self.make_header(config, use_agent = nil) + return if config.nil? || config == OPT_OUT - header = new(config) - [HEADER_NAME, header.value] - end + header = new(config) + [HEADER_NAME, header.value] + end - def validate_config!(config) - return if config.nil? || config == OPT_OUT - raise ExpectCertificateTransparencyConfigError.new(INVALID_CONFIGURATION_ERROR) unless config.is_a? Hash + def self.validate_config!(config) + return if config.nil? || config == OPT_OUT + raise ExpectCertificateTransparencyConfigError.new(INVALID_CONFIGURATION_ERROR) unless config.is_a? Hash - unless [true, false, nil].include?(config[:enforce]) - raise ExpectCertificateTransparencyConfigError.new(INVALID_ENFORCE_VALUE_ERROR) - end + unless [true, false, nil].include?(config[:enforce]) + raise ExpectCertificateTransparencyConfigError.new(INVALID_ENFORCE_VALUE_ERROR) + end - if !config[:max_age] - raise ExpectCertificateTransparencyConfigError.new(REQUIRED_MAX_AGE_ERROR) - elsif config[:max_age].to_s !~ /\A\d+\z/ - raise ExpectCertificateTransparencyConfigError.new(INVALID_MAX_AGE_ERROR) - end + if !config[:max_age] + raise ExpectCertificateTransparencyConfigError.new(REQUIRED_MAX_AGE_ERROR) + elsif config[:max_age].to_s !~ /\A\d+\z/ + raise ExpectCertificateTransparencyConfigError.new(INVALID_MAX_AGE_ERROR) end end diff --git a/lib/secure_headers/headers/referrer_policy.rb b/lib/secure_headers/headers/referrer_policy.rb index a4589117..2094656c 100644 --- a/lib/secure_headers/headers/referrer_policy.rb +++ b/lib/secure_headers/headers/referrer_policy.rb @@ -15,29 +15,27 @@ class ReferrerPolicy unsafe-url ) - class << self - # Public: generate an Referrer Policy header. - # - # Returns a default header if no configuration is provided, or a - # header name and value based on the config. - def make_header(config = nil, user_agent = nil) - return if config == OPT_OUT - config ||= DEFAULT_VALUE - [HEADER_NAME, Array(config).join(", ")] - end + # Public: generate an Referrer Policy header. + # + # Returns a default header if no configuration is provided, or a + # header name and value based on the config. + def self.make_header(config = nil, user_agent = nil) + return if config == OPT_OUT + config ||= DEFAULT_VALUE + [HEADER_NAME, Array(config).join(", ")] + end - def validate_config!(config) - case config - when nil, OPT_OUT - # valid - when String, Array - config = Array(config) - unless config.all? { |t| t.is_a?(String) && VALID_POLICIES.include?(t.downcase) } - raise ReferrerPolicyConfigError.new("Value can only be one or more of #{VALID_POLICIES.join(", ")}") - end - else - raise TypeError.new("Must be a string or array of strings. Found #{config.class}: #{config}") + def self.validate_config!(config) + case config + when nil, OPT_OUT + # valid + when String, Array + config = Array(config) + unless config.all? { |t| t.is_a?(String) && VALID_POLICIES.include?(t.downcase) } + raise ReferrerPolicyConfigError.new("Value can only be one or more of #{VALID_POLICIES.join(", ")}") end + else + raise TypeError.new("Must be a string or array of strings. Found #{config.class}: #{config}") end end end diff --git a/lib/secure_headers/headers/strict_transport_security.rb b/lib/secure_headers/headers/strict_transport_security.rb index 3d78a484..eaf46cb6 100644 --- a/lib/secure_headers/headers/strict_transport_security.rb +++ b/lib/secure_headers/headers/strict_transport_security.rb @@ -9,21 +9,19 @@ class StrictTransportSecurity VALID_STS_HEADER = /\Amax-age=\d+(; includeSubdomains)?(; preload)?\z/i MESSAGE = "The config value supplied for the HSTS header was invalid. Must match #{VALID_STS_HEADER}" - class << self - # Public: generate an hsts header name, value pair. - # - # Returns a default header if no configuration is provided, or a - # header name and value based on the config. - def make_header(config = nil, user_agent = nil) - return if config == OPT_OUT - [HEADER_NAME, config || DEFAULT_VALUE] - end + # Public: generate an hsts header name, value pair. + # + # Returns a default header if no configuration is provided, or a + # header name and value based on the config. + def self.make_header(config = nil, user_agent = nil) + return if config == OPT_OUT + [HEADER_NAME, config || DEFAULT_VALUE] + end - def validate_config!(config) - return if config.nil? || config == OPT_OUT - raise TypeError.new("Must be a string. Found #{config.class}: #{config} #{config.class}") unless config.is_a?(String) - raise STSConfigError.new(MESSAGE) unless config =~ VALID_STS_HEADER - end + def self.validate_config!(config) + return if config.nil? || config == OPT_OUT + raise TypeError.new("Must be a string. Found #{config.class}: #{config} #{config.class}") unless config.is_a?(String) + raise STSConfigError.new(MESSAGE) unless config =~ VALID_STS_HEADER end end end diff --git a/lib/secure_headers/headers/x_content_type_options.rb b/lib/secure_headers/headers/x_content_type_options.rb index 96f8d314..773bad82 100644 --- a/lib/secure_headers/headers/x_content_type_options.rb +++ b/lib/secure_headers/headers/x_content_type_options.rb @@ -6,22 +6,20 @@ class XContentTypeOptions HEADER_NAME = "x-content-type-options".freeze DEFAULT_VALUE = "nosniff" - class << self - # Public: generate an X-Content-Type-Options header. - # - # Returns a default header if no configuration is provided, or a - # header name and value based on the config. - def make_header(config = nil, user_agent = nil) - return if config == OPT_OUT - [HEADER_NAME, config || DEFAULT_VALUE] - end + # Public: generate an X-Content-Type-Options header. + # + # Returns a default header if no configuration is provided, or a + # header name and value based on the config. + def self.make_header(config = nil, user_agent = nil) + return if config == OPT_OUT + [HEADER_NAME, config || DEFAULT_VALUE] + end - def validate_config!(config) - return if config.nil? || config == OPT_OUT - raise TypeError.new("Must be a string. Found #{config.class}: #{config}") unless config.is_a?(String) - unless config.casecmp(DEFAULT_VALUE) == 0 - raise XContentTypeOptionsConfigError.new("Value can only be nil or 'nosniff'") - end + def self.validate_config!(config) + return if config.nil? || config == OPT_OUT + raise TypeError.new("Must be a string. Found #{config.class}: #{config}") unless config.is_a?(String) + unless config.casecmp(DEFAULT_VALUE) == 0 + raise XContentTypeOptionsConfigError.new("Value can only be nil or 'nosniff'") end end end diff --git a/lib/secure_headers/headers/x_download_options.rb b/lib/secure_headers/headers/x_download_options.rb index 1eb1356a..0042e9d0 100644 --- a/lib/secure_headers/headers/x_download_options.rb +++ b/lib/secure_headers/headers/x_download_options.rb @@ -5,22 +5,20 @@ class XDownloadOptions HEADER_NAME = "x-download-options".freeze DEFAULT_VALUE = "noopen" - class << self - # 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. - def make_header(config = nil, user_agent = nil) - return if config == OPT_OUT - [HEADER_NAME, config || DEFAULT_VALUE] - end + # 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. + def self.make_header(config = nil, user_agent = nil) + return if config == OPT_OUT + [HEADER_NAME, config || DEFAULT_VALUE] + end - def validate_config!(config) - return if config.nil? || config == OPT_OUT - raise TypeError.new("Must be a string. Found #{config.class}: #{config}") unless config.is_a?(String) - unless config.casecmp(DEFAULT_VALUE) == 0 - raise XDOConfigError.new("Value can only be nil or 'noopen'") - end + def self.validate_config!(config) + return if config.nil? || config == OPT_OUT + raise TypeError.new("Must be a string. Found #{config.class}: #{config}") unless config.is_a?(String) + unless config.casecmp(DEFAULT_VALUE) == 0 + raise XDOConfigError.new("Value can only be nil or 'noopen'") end end end diff --git a/lib/secure_headers/headers/x_frame_options.rb b/lib/secure_headers/headers/x_frame_options.rb index 636e3bfa..9788ca3e 100644 --- a/lib/secure_headers/headers/x_frame_options.rb +++ b/lib/secure_headers/headers/x_frame_options.rb @@ -10,22 +10,20 @@ class XFrameOptions DEFAULT_VALUE = SAMEORIGIN VALID_XFO_HEADER = /\A(#{SAMEORIGIN}\z|#{DENY}\z|#{ALLOW_ALL}\z|#{ALLOW_FROM}[:\s])/i - class << self - # Public: generate an X-Frame-Options header. - # - # Returns a default header if no configuration is provided, or a - # header name and value based on the config. - def make_header(config = nil, user_agent = nil) - return if config == OPT_OUT - [HEADER_NAME, config || DEFAULT_VALUE] - end + # Public: generate an X-Frame-Options header. + # + # Returns a default header if no configuration is provided, or a + # header name and value based on the config. + def self.make_header(config = nil, user_agent = nil) + return if config == OPT_OUT + [HEADER_NAME, config || DEFAULT_VALUE] + end - def validate_config!(config) - return if config.nil? || config == OPT_OUT - raise TypeError.new("Must be a string. Found #{config.class}: #{config}") unless config.is_a?(String) - unless config =~ VALID_XFO_HEADER - raise XFOConfigError.new("Value must be SAMEORIGIN|DENY|ALLOW-FROM:|ALLOWALL") - end + def self.validate_config!(config) + return if config.nil? || config == OPT_OUT + raise TypeError.new("Must be a string. Found #{config.class}: #{config}") unless config.is_a?(String) + unless config =~ VALID_XFO_HEADER + raise XFOConfigError.new("Value must be SAMEORIGIN|DENY|ALLOW-FROM:|ALLOWALL") end end end 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 a34dd58f..4ca81b68 100644 --- a/lib/secure_headers/headers/x_permitted_cross_domain_policies.rb +++ b/lib/secure_headers/headers/x_permitted_cross_domain_policies.rb @@ -6,22 +6,20 @@ class XPermittedCrossDomainPolicies 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. - # - # Returns a default header if no configuration is provided, or a - # header name and value based on the config. - def make_header(config = nil, user_agent = nil) - return if config == OPT_OUT - [HEADER_NAME, config || DEFAULT_VALUE] - end + # 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. + def self.make_header(config = nil, user_agent = nil) + return if config == OPT_OUT + [HEADER_NAME, config || DEFAULT_VALUE] + end - def validate_config!(config) - return if config.nil? || config == OPT_OUT - raise TypeError.new("Must be a string. Found #{config.class}: #{config}") unless config.is_a?(String) - unless VALID_POLICIES.include?(config.downcase) - raise XPCDPConfigError.new("Value can only be one of #{VALID_POLICIES.join(', ')}") - end + def self.validate_config!(config) + return if config.nil? || config == OPT_OUT + raise TypeError.new("Must be a string. Found #{config.class}: #{config}") unless config.is_a?(String) + unless VALID_POLICIES.include?(config.downcase) + raise XPCDPConfigError.new("Value can only be one of #{VALID_POLICIES.join(', ')}") end end end diff --git a/lib/secure_headers/headers/x_xss_protection.rb b/lib/secure_headers/headers/x_xss_protection.rb index bd5b7faa..756bc4c3 100644 --- a/lib/secure_headers/headers/x_xss_protection.rb +++ b/lib/secure_headers/headers/x_xss_protection.rb @@ -6,21 +6,19 @@ class XXssProtection DEFAULT_VALUE = "0".freeze VALID_X_XSS_HEADER = /\A[01](; mode=block)?(; report=.*)?\z/ - class << self - # Public: generate an X-Xss-Protection header. - # - # Returns a default header if no configuration is provided, or a - # header name and value based on the config. - def make_header(config = nil, user_agent = nil) - return if config == OPT_OUT - [HEADER_NAME, config || DEFAULT_VALUE] - end + # Public: generate an X-Xss-Protection header. + # + # Returns a default header if no configuration is provided, or a + # header name and value based on the config. + def self.make_header(config = nil, user_agent = nil) + return if config == OPT_OUT + [HEADER_NAME, config || DEFAULT_VALUE] + end - def validate_config!(config) - return if config.nil? || config == OPT_OUT - raise TypeError.new("Must be a string. Found #{config.class}: #{config}") unless config.is_a?(String) - raise XXssProtectionConfigError.new("Invalid format (see VALID_X_XSS_HEADER)") unless config.to_s =~ VALID_X_XSS_HEADER - end + def self.validate_config!(config) + return if config.nil? || config == OPT_OUT + raise TypeError.new("Must be a string. Found #{config.class}: #{config}") unless config.is_a?(String) + raise XXssProtectionConfigError.new("Invalid format (see VALID_X_XSS_HEADER)") unless config.to_s =~ VALID_X_XSS_HEADER end end end diff --git a/spec/lib/secure_headers/configuration_spec.rb b/spec/lib/secure_headers/configuration_spec.rb index 73e9b16b..1c613658 100644 --- a/spec/lib/secure_headers/configuration_spec.rb +++ b/spec/lib/secure_headers/configuration_spec.rb @@ -22,7 +22,9 @@ module SecureHeaders configuration = Configuration.dup expect(original_configuration).not_to be(configuration) Configuration::CONFIG_ATTRIBUTES.each do |attr| - expect(original_configuration.send(attr)).to eq(configuration.send(attr)) + # rubocop:disable GitHub/AvoidObjectSendWithDynamicMethod + expect(original_configuration.public_send(attr)).to eq(configuration.public_send(attr)) + # rubocop:enable GitHub/AvoidObjectSendWithDynamicMethod end end @@ -97,7 +99,7 @@ module SecureHeaders end it "gives cookies a default config" do - expect(Configuration.default.cookies).to eq({httponly: true, secure: true, samesite: {lax: true}}) + expect(Configuration.default.cookies).to eq({ httponly: true, secure: true, samesite: { lax: true } }) end it "allows OPT_OUT" do @@ -111,11 +113,11 @@ module SecureHeaders it "allows me to be explicit too" do Configuration.default do |config| - config.cookies = {httponly: true, secure: true, samesite: {lax: false}} + config.cookies = { httponly: true, secure: true, samesite: { lax: false } } end config = Configuration.dup - expect(config.cookies).to eq({httponly: true, secure: true, samesite: {lax: false}}) + expect(config.cookies).to eq({ httponly: true, secure: true, samesite: { lax: false } }) end end end diff --git a/spec/lib/secure_headers/headers/content_security_policy_spec.rb b/spec/lib/secure_headers/headers/content_security_policy_spec.rb index 37cb62a7..c16e70a2 100644 --- a/spec/lib/secure_headers/headers/content_security_policy_spec.rb +++ b/spec/lib/secure_headers/headers/content_security_policy_spec.rb @@ -3,7 +3,7 @@ module SecureHeaders describe ContentSecurityPolicy do - let (:default_opts) do + let(:default_opts) do { default_src: %w(https:), img_src: %w(https: data:), @@ -167,47 +167,47 @@ module SecureHeaders end it "supports strict-dynamic" do - csp = ContentSecurityPolicy.new({default_src: %w('self'), script_src: [ContentSecurityPolicy::STRICT_DYNAMIC], script_nonce: 123456}) + csp = ContentSecurityPolicy.new({ default_src: %w('self'), script_src: [ContentSecurityPolicy::STRICT_DYNAMIC], script_nonce: 123456 }) expect(csp.value).to eq("default-src 'self'; script-src 'strict-dynamic' 'nonce-123456' 'unsafe-inline'") end it "supports strict-dynamic and opting out of the appended 'unsafe-inline'" do - csp = ContentSecurityPolicy.new({default_src: %w('self'), script_src: [ContentSecurityPolicy::STRICT_DYNAMIC], script_nonce: 123456, disable_nonce_backwards_compatibility: true }) + csp = ContentSecurityPolicy.new({ default_src: %w('self'), script_src: [ContentSecurityPolicy::STRICT_DYNAMIC], script_nonce: 123456, disable_nonce_backwards_compatibility: true }) expect(csp.value).to eq("default-src 'self'; script-src 'strict-dynamic' 'nonce-123456'") end it "supports script-src-elem directive" do - csp = ContentSecurityPolicy.new({script_src: %w('self'), script_src_elem: %w('self')}) + csp = ContentSecurityPolicy.new({ script_src: %w('self'), script_src_elem: %w('self') }) expect(csp.value).to eq("script-src 'self'; script-src-elem 'self'") end it "supports script-src-attr directive" do - csp = ContentSecurityPolicy.new({script_src: %w('self'), script_src_attr: %w('self')}) + csp = ContentSecurityPolicy.new({ script_src: %w('self'), script_src_attr: %w('self') }) expect(csp.value).to eq("script-src 'self'; script-src-attr 'self'") end it "supports style-src-elem directive" do - csp = ContentSecurityPolicy.new({style_src: %w('self'), style_src_elem: %w('self')}) + csp = ContentSecurityPolicy.new({ style_src: %w('self'), style_src_elem: %w('self') }) expect(csp.value).to eq("style-src 'self'; style-src-elem 'self'") end it "supports style-src-attr directive" do - csp = ContentSecurityPolicy.new({style_src: %w('self'), style_src_attr: %w('self')}) + csp = ContentSecurityPolicy.new({ style_src: %w('self'), style_src_attr: %w('self') }) expect(csp.value).to eq("style-src 'self'; style-src-attr 'self'") end it "supports trusted-types directive" do - csp = ContentSecurityPolicy.new({trusted_types: %w(blahblahpolicy)}) + csp = ContentSecurityPolicy.new({ trusted_types: %w(blahblahpolicy) }) expect(csp.value).to eq("trusted-types blahblahpolicy") end it "supports trusted-types directive with 'none'" do - csp = ContentSecurityPolicy.new({trusted_types: %w('none')}) + csp = ContentSecurityPolicy.new({ trusted_types: %w('none') }) expect(csp.value).to eq("trusted-types 'none'") end it "allows duplicate policy names in trusted-types directive" do - csp = ContentSecurityPolicy.new({trusted_types: %w(blahblahpolicy 'allow-duplicates')}) + csp = ContentSecurityPolicy.new({ trusted_types: %w(blahblahpolicy 'allow-duplicates') }) expect(csp.value).to eq("trusted-types blahblahpolicy 'allow-duplicates'") end end diff --git a/spec/lib/secure_headers/headers/cookie_spec.rb b/spec/lib/secure_headers/headers/cookie_spec.rb index cdb24246..b0a9152b 100644 --- a/spec/lib/secure_headers/headers/cookie_spec.rb +++ b/spec/lib/secure_headers/headers/cookie_spec.rb @@ -35,7 +35,7 @@ module SecureHeaders context "when configured with a Hash" do it "flags cookies as Secure when whitelisted" do - cookie = Cookie.new(raw_cookie, secure: { only: ["_session"]}, httponly: OPT_OUT, samesite: OPT_OUT) + cookie = Cookie.new(raw_cookie, secure: { only: ["_session"] }, httponly: OPT_OUT, samesite: OPT_OUT) expect(cookie.to_s).to eq("_session=thisisatest; secure") end @@ -56,7 +56,7 @@ module SecureHeaders context "when configured with a Hash" do it "flags cookies as HttpOnly when whitelisted" do - cookie = Cookie.new(raw_cookie, httponly: { only: ["_session"]}, secure: OPT_OUT, samesite: OPT_OUT) + cookie = Cookie.new(raw_cookie, httponly: { only: ["_session"] }, secure: OPT_OUT, samesite: OPT_OUT) expect(cookie.to_s).to eq("_session=thisisatest; HttpOnly") end @@ -75,7 +75,7 @@ module SecureHeaders end it "flags SameSite=#{flag} when configured with a boolean" do - cookie = Cookie.new(raw_cookie, samesite: { flag.downcase.to_sym => true}, secure: OPT_OUT, httponly: OPT_OUT) + cookie = Cookie.new(raw_cookie, samesite: { flag.downcase.to_sym => true }, secure: OPT_OUT, httponly: OPT_OUT) expect(cookie.to_s).to eq("_session=thisisatest; SameSite=#{flag}") end @@ -86,7 +86,7 @@ module SecureHeaders end it "flags SameSite=Strict when configured with a boolean" do - cookie = Cookie.new(raw_cookie, {samesite: { strict: true}, secure: OPT_OUT, httponly: OPT_OUT}) + cookie = Cookie.new(raw_cookie, { samesite: { strict: true }, secure: OPT_OUT, httponly: OPT_OUT }) expect(cookie.to_s).to eq("_session=thisisatest; SameSite=Strict") end @@ -146,7 +146,7 @@ module SecureHeaders (cookie_options - [flag]).each do |other_flag| it "raises an exception when SameSite #{flag} and #{other_flag} enforcement modes are configured with booleans" do expect do - Cookie.validate_config!(samesite: { flag => true, other_flag => true}) + Cookie.validate_config!(samesite: { flag => true, other_flag => true }) end.to raise_error(CookiesConfigError) end end diff --git a/spec/lib/secure_headers/headers/policy_management_spec.rb b/spec/lib/secure_headers/headers/policy_management_spec.rb index c621e88e..99065744 100644 --- a/spec/lib/secure_headers/headers/policy_management_spec.rb +++ b/spec/lib/secure_headers/headers/policy_management_spec.rb @@ -8,7 +8,7 @@ module SecureHeaders Configuration.default end - let (:default_opts) do + let(:default_opts) do { default_src: %w(https:), img_src: %w(https: data:), diff --git a/spec/lib/secure_headers/middleware_spec.rb b/spec/lib/secure_headers/middleware_spec.rb index b3925f85..f46a6979 100644 --- a/spec/lib/secure_headers/middleware_spec.rb +++ b/spec/lib/secure_headers/middleware_spec.rb @@ -42,7 +42,7 @@ module SecureHeaders end context "cookies should be flagged" do it "flags cookies as secure" do - Configuration.default { |config| config.cookies = {secure: true, httponly: OPT_OUT, samesite: OPT_OUT} } + Configuration.default { |config| config.cookies = { secure: true, httponly: OPT_OUT, samesite: OPT_OUT } } request = Rack::Request.new("HTTPS" => "on") _, env = cookie_middleware.call request.env expect(env["Set-Cookie"]).to eq("foo=bar; secure") @@ -62,7 +62,7 @@ module SecureHeaders context "cookies should not be flagged" do it "does not flags cookies as secure" do - Configuration.default { |config| config.cookies = {secure: OPT_OUT, httponly: OPT_OUT, samesite: OPT_OUT} } + Configuration.default { |config| config.cookies = { secure: OPT_OUT, httponly: OPT_OUT, samesite: OPT_OUT } } request = Rack::Request.new("HTTPS" => "on") _, env = cookie_middleware.call request.env expect(env["Set-Cookie"]).to eq("foo=bar") @@ -75,7 +75,7 @@ module SecureHeaders reset_config end it "flags cookies from configuration" do - Configuration.default { |config| config.cookies = { secure: true, httponly: true, samesite: { lax: true} } } + Configuration.default { |config| config.cookies = { secure: true, httponly: true, samesite: { lax: true } } } request = Rack::Request.new("HTTPS" => "on") _, env = cookie_middleware.call request.env @@ -85,7 +85,7 @@ module SecureHeaders it "flags cookies with a combination of SameSite configurations" do cookie_middleware = Middleware.new(lambda { |env| [200, env.merge("Set-Cookie" => ["_session=foobar", "_guest=true"]), "app"] }) - Configuration.default { |config| config.cookies = { samesite: { lax: { except: ["_session"] }, strict: { only: ["_session"] } }, httponly: OPT_OUT, secure: OPT_OUT} } + Configuration.default { |config| config.cookies = { samesite: { lax: { except: ["_session"] }, strict: { only: ["_session"] } }, httponly: OPT_OUT, secure: OPT_OUT } } request = Rack::Request.new("HTTPS" => "on") _, env = cookie_middleware.call request.env diff --git a/spec/lib/secure_headers_spec.rb b/spec/lib/secure_headers_spec.rb index fd66d487..76d51baf 100644 --- a/spec/lib/secure_headers_spec.rb +++ b/spec/lib/secure_headers_spec.rb @@ -54,7 +54,7 @@ module SecureHeaders describe "#header_hash_for" do it "allows you to opt out of individual headers via API" do Configuration.default do |config| - config.csp = { default_src: %w('self'), script_src: %w('self')} + config.csp = { default_src: %w('self'), script_src: %w('self') } config.csp_report_only = config.csp end SecureHeaders.opt_out_of_header(request, :csp) @@ -174,11 +174,11 @@ module SecureHeaders end Configuration.named_append(:moar_default_sources) do |request| - { default_src: %w(https:), style_src: %w('self')} + { default_src: %w(https:), style_src: %w('self') } end Configuration.named_append(:how_about_a_script_src_too) do |request| - { script_src: %w('unsafe-inline')} + { script_src: %w('unsafe-inline') } end SecureHeaders.use_content_security_policy_named_append(request, :moar_default_sources) @@ -318,7 +318,7 @@ module SecureHeaders default_src: %w('self'), script_src: %w('self') } - config.csp_report_only = config.csp.merge({script_src: %w(foo.com)}) + config.csp_report_only = config.csp.merge({ script_src: %w(foo.com) }) end hash = SecureHeaders.header_hash_for(request) @@ -342,42 +342,42 @@ module SecureHeaders end it "allows appending to the enforced policy" do - SecureHeaders.append_content_security_policy_directives(request, {script_src: %w(anothercdn.com)}, :enforced) + 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'") end it "allows appending to the report only policy" do - SecureHeaders.append_content_security_policy_directives(request, {script_src: %w(anothercdn.com)}, :report_only) + 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") end it "allows appending to both policies" do - SecureHeaders.append_content_security_policy_directives(request, {script_src: %w(anothercdn.com)}, :both) + 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") end it "allows overriding the enforced policy" do - SecureHeaders.override_content_security_policy_directives(request, {script_src: %w(anothercdn.com)}, :enforced) + 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'") end it "allows overriding the report only policy" do - SecureHeaders.override_content_security_policy_directives(request, {script_src: %w(anothercdn.com)}, :report_only) + 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") end it "allows overriding both policies" do - SecureHeaders.override_content_security_policy_directives(request, {script_src: %w(anothercdn.com)}, :both) + 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") @@ -392,7 +392,7 @@ module SecureHeaders script_src: %w('self') } end - SecureHeaders.append_content_security_policy_directives(request, {script_src: %w(anothercdn.com)}) + 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") @@ -408,7 +408,7 @@ module SecureHeaders script_src: %w('self') } end - SecureHeaders.append_content_security_policy_directives(request, {script_src: %w(anothercdn.com)}) + 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") @@ -427,7 +427,7 @@ module SecureHeaders script_src: %w('self') } end - SecureHeaders.append_content_security_policy_directives(request, {script_src: %w(anothercdn.com)}) + 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") diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b0c774d9..65627eec 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -41,18 +41,16 @@ def expect_default_values(hash) module SecureHeaders class Configuration - class << self - def clear_default_config - remove_instance_variable(:@default_config) if defined?(@default_config) - end + def self.clear_default_config + remove_instance_variable(:@default_config) if defined?(@default_config) + end - def clear_overrides - remove_instance_variable(:@overrides) if defined?(@overrides) - end + def self.clear_overrides + remove_instance_variable(:@overrides) if defined?(@overrides) + end - def clear_appends - remove_instance_variable(:@appends) if defined?(@appends) - end + def self.clear_appends + remove_instance_variable(:@appends) if defined?(@appends) end end end