Skip to content

Commit 8cafd03

Browse files
committed
Merge branch 'main' into myersg86/main
2 parents f57f3fd + 33d6461 commit 8cafd03

22 files changed

+207
-218
lines changed

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ jobs:
1010
runs-on: ubuntu-latest
1111
strategy:
1212
matrix:
13-
ruby: [ '2.6', '2.7', '3.0', '3.1', '3.2' ]
13+
ruby: [ '2.7', '3.0', '3.1', '3.2', '3.4', '4.0' ]
1414

1515
steps:
1616
- uses: actions/checkout@v4
1717
- name: Set up Ruby ${{ matrix.ruby }}
18-
uses: ruby/setup-ruby@4a9ddd6f338a97768b8006bf671dfbad383215f4 #v1.190.0 tag
18+
uses: ruby/setup-ruby@d697be2f83c6234b20877c3b5eac7a7f342f0d0c #v1.269.0 tag
1919
with:
2020
ruby-version: ${{ matrix.ruby }}
2121
bundler-cache: true

.rubocop.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
inherit_gem:
22
rubocop-github:
33
- config/default.yml
4-
require: rubocop-performance
4+
plugins: rubocop-performance
5+
6+
AllCops:
7+
TargetRubyVersion: 2.6
8+
9+
# Disable cops that are not consistently available across all Ruby versions
10+
Lint/RedundantCopDisableDirective:
11+
Enabled: false

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Secure Headers ![Build + Test](https://github.com/github/secure_headers/workflows/Build%20+%20Test/badge.svg?branch=main)
1+
# Secure Headers [![Build + Test](https://github.com/github/secure_headers/actions/workflows/build.yml/badge.svg)](https://github.com/github/secure_headers/actions/workflows/build.yml)
22

33
**main branch represents 7.x line**. See the [upgrading to 4.x doc](docs/upgrading-to-4-0.md), [upgrading to 5.x doc](docs/upgrading-to-5-0.md), [upgrading to 6.x doc](docs/upgrading-to-6-0.md) or [upgrading to 7.x doc](docs/upgrading-to-7-0.md) for instructions on how to upgrade. Bug fixes should go in the `6.x` branch for now.
44

lib/secure_headers.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ def raise_on_unknown_target(target)
208208

209209
def config_and_target(request, target)
210210
config = config_for(request)
211-
target = guess_target(config) unless target
211+
target ||= guess_target(config)
212212
raise_on_unknown_target(target)
213213
[config, target]
214214
end

lib/secure_headers/headers/clear_site_data.rb

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -11,43 +11,41 @@ class ClearSiteData
1111
EXECUTION_CONTEXTS = "executionContexts".freeze
1212
ALL_TYPES = [CACHE, COOKIES, STORAGE, EXECUTION_CONTEXTS]
1313

14-
class << self
15-
# Public: make an clear-site-data header name, value pair
16-
#
17-
# Returns nil if not configured, returns header name and value if configured.
18-
def make_header(config = nil, user_agent = nil)
19-
case config
20-
when nil, OPT_OUT, []
21-
# noop
22-
when Array
23-
[HEADER_NAME, make_header_value(config)]
24-
when true
25-
[HEADER_NAME, make_header_value(ALL_TYPES)]
26-
end
14+
# Public: make an clear-site-data header name, value pair
15+
#
16+
# Returns nil if not configured, returns header name and value if configured.
17+
def self.make_header(config = nil, user_agent = nil)
18+
case config
19+
when nil, OPT_OUT, []
20+
# noop
21+
when Array
22+
[HEADER_NAME, make_header_value(config)]
23+
when true
24+
[HEADER_NAME, make_header_value(ALL_TYPES)]
2725
end
26+
end
2827

29-
def validate_config!(config)
30-
case config
31-
when nil, OPT_OUT, true
32-
# valid
33-
when Array
34-
unless config.all? { |t| t.is_a?(String) }
35-
raise ClearSiteDataConfigError.new("types must be Strings")
36-
end
37-
else
38-
raise ClearSiteDataConfigError.new("config must be an Array of Strings or `true`")
28+
def self.validate_config!(config)
29+
case config
30+
when nil, OPT_OUT, true
31+
# valid
32+
when Array
33+
unless config.all? { |t| t.is_a?(String) }
34+
raise ClearSiteDataConfigError.new("types must be Strings")
3935
end
36+
else
37+
raise ClearSiteDataConfigError.new("config must be an Array of Strings or `true`")
4038
end
39+
end
4140

42-
# Public: Transform a clear-site-data config (an Array of Strings) into a
43-
# String that can be used as the value for the clear-site-data header.
44-
#
45-
# types - An Array of String of types of data to clear.
46-
#
47-
# Returns a String of quoted values that are comma separated.
48-
def make_header_value(types)
49-
types.map { |t| %("#{t}") }.join(", ")
50-
end
41+
# Public: Transform a clear-site-data config (an Array of Strings) into a
42+
# String that can be used as the value for the clear-site-data header.
43+
#
44+
# types - An Array of String of types of data to clear.
45+
#
46+
# Returns a String of quoted values that are comma separated.
47+
def self.make_header_value(types)
48+
types.map { |t| %("#{t}") }.join(", ")
5149
end
5250
end
5351
end

lib/secure_headers/headers/cookie.rb

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@ module SecureHeaders
77
class CookiesConfigError < StandardError; end
88
class Cookie
99

10-
class << self
11-
def validate_config!(config)
12-
CookiesConfig.new(config).validate!
13-
end
10+
def self.validate_config!(config)
11+
CookiesConfig.new(config).validate!
1412
end
1513

1614
attr_reader :raw_cookie, :config

lib/secure_headers/headers/expect_certificate_transparency.rb

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,31 +9,29 @@ class ExpectCertificateTransparency
99
REQUIRED_MAX_AGE_ERROR = "max-age is a required directive.".freeze
1010
INVALID_MAX_AGE_ERROR = "max-age must be a number.".freeze
1111

12-
class << self
13-
# Public: Generate a expect-ct header.
14-
#
15-
# Returns nil if not configured, returns header name and value if
16-
# configured.
17-
def make_header(config, use_agent = nil)
18-
return if config.nil? || config == OPT_OUT
12+
# Public: Generate a expect-ct header.
13+
#
14+
# Returns nil if not configured, returns header name and value if
15+
# configured.
16+
def self.make_header(config, use_agent = nil)
17+
return if config.nil? || config == OPT_OUT
1918

20-
header = new(config)
21-
[HEADER_NAME, header.value]
22-
end
19+
header = new(config)
20+
[HEADER_NAME, header.value]
21+
end
2322

24-
def validate_config!(config)
25-
return if config.nil? || config == OPT_OUT
26-
raise ExpectCertificateTransparencyConfigError.new(INVALID_CONFIGURATION_ERROR) unless config.is_a? Hash
23+
def self.validate_config!(config)
24+
return if config.nil? || config == OPT_OUT
25+
raise ExpectCertificateTransparencyConfigError.new(INVALID_CONFIGURATION_ERROR) unless config.is_a? Hash
2726

28-
unless [true, false, nil].include?(config[:enforce])
29-
raise ExpectCertificateTransparencyConfigError.new(INVALID_ENFORCE_VALUE_ERROR)
30-
end
27+
unless [true, false, nil].include?(config[:enforce])
28+
raise ExpectCertificateTransparencyConfigError.new(INVALID_ENFORCE_VALUE_ERROR)
29+
end
3130

32-
if !config[:max_age]
33-
raise ExpectCertificateTransparencyConfigError.new(REQUIRED_MAX_AGE_ERROR)
34-
elsif config[:max_age].to_s !~ /\A\d+\z/
35-
raise ExpectCertificateTransparencyConfigError.new(INVALID_MAX_AGE_ERROR)
36-
end
31+
if !config[:max_age]
32+
raise ExpectCertificateTransparencyConfigError.new(REQUIRED_MAX_AGE_ERROR)
33+
elsif config[:max_age].to_s !~ /\A\d+\z/
34+
raise ExpectCertificateTransparencyConfigError.new(INVALID_MAX_AGE_ERROR)
3735
end
3836
end
3937

lib/secure_headers/headers/referrer_policy.rb

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,27 @@ class ReferrerPolicy
1515
unsafe-url
1616
)
1717

18-
class << self
19-
# Public: generate an Referrer Policy header.
20-
#
21-
# Returns a default header if no configuration is provided, or a
22-
# header name and value based on the config.
23-
def make_header(config = nil, user_agent = nil)
24-
return if config == OPT_OUT
25-
config ||= DEFAULT_VALUE
26-
[HEADER_NAME, Array(config).join(", ")]
27-
end
18+
# Public: generate an Referrer Policy header.
19+
#
20+
# Returns a default header if no configuration is provided, or a
21+
# header name and value based on the config.
22+
def self.make_header(config = nil, user_agent = nil)
23+
return if config == OPT_OUT
24+
config ||= DEFAULT_VALUE
25+
[HEADER_NAME, Array(config).join(", ")]
26+
end
2827

29-
def validate_config!(config)
30-
case config
31-
when nil, OPT_OUT
32-
# valid
33-
when String, Array
34-
config = Array(config)
35-
unless config.all? { |t| t.is_a?(String) && VALID_POLICIES.include?(t.downcase) }
36-
raise ReferrerPolicyConfigError.new("Value can only be one or more of #{VALID_POLICIES.join(", ")}")
37-
end
38-
else
39-
raise TypeError.new("Must be a string or array of strings. Found #{config.class}: #{config}")
28+
def self.validate_config!(config)
29+
case config
30+
when nil, OPT_OUT
31+
# valid
32+
when String, Array
33+
config = Array(config)
34+
unless config.all? { |t| t.is_a?(String) && VALID_POLICIES.include?(t.downcase) }
35+
raise ReferrerPolicyConfigError.new("Value can only be one or more of #{VALID_POLICIES.join(", ")}")
4036
end
37+
else
38+
raise TypeError.new("Must be a string or array of strings. Found #{config.class}: #{config}")
4139
end
4240
end
4341
end

lib/secure_headers/headers/strict_transport_security.rb

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,19 @@ class StrictTransportSecurity
99
VALID_STS_HEADER = /\Amax-age=\d+(; includeSubdomains)?(; preload)?\z/i
1010
MESSAGE = "The config value supplied for the HSTS header was invalid. Must match #{VALID_STS_HEADER}"
1111

12-
class << self
13-
# Public: generate an hsts header name, value pair.
14-
#
15-
# Returns a default header if no configuration is provided, or a
16-
# header name and value based on the config.
17-
def make_header(config = nil, user_agent = nil)
18-
return if config == OPT_OUT
19-
[HEADER_NAME, config || DEFAULT_VALUE]
20-
end
12+
# Public: generate an hsts header name, value pair.
13+
#
14+
# Returns a default header if no configuration is provided, or a
15+
# header name and value based on the config.
16+
def self.make_header(config = nil, user_agent = nil)
17+
return if config == OPT_OUT
18+
[HEADER_NAME, config || DEFAULT_VALUE]
19+
end
2120

22-
def validate_config!(config)
23-
return if config.nil? || config == OPT_OUT
24-
raise TypeError.new("Must be a string. Found #{config.class}: #{config} #{config.class}") unless config.is_a?(String)
25-
raise STSConfigError.new(MESSAGE) unless config =~ VALID_STS_HEADER
26-
end
21+
def self.validate_config!(config)
22+
return if config.nil? || config == OPT_OUT
23+
raise TypeError.new("Must be a string. Found #{config.class}: #{config} #{config.class}") unless config.is_a?(String)
24+
raise STSConfigError.new(MESSAGE) unless config =~ VALID_STS_HEADER
2725
end
2826
end
2927
end

lib/secure_headers/headers/x_content_type_options.rb

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,20 @@ class XContentTypeOptions
66
HEADER_NAME = "x-content-type-options".freeze
77
DEFAULT_VALUE = "nosniff"
88

9-
class << self
10-
# Public: generate an X-Content-Type-Options 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-Content-Type-Options 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
1817

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 config.casecmp(DEFAULT_VALUE) == 0
23-
raise XContentTypeOptionsConfigError.new("Value can only be nil or 'nosniff'")
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 config.casecmp(DEFAULT_VALUE) == 0
22+
raise XContentTypeOptionsConfigError.new("Value can only be nil or 'nosniff'")
2523
end
2624
end
2725
end

0 commit comments

Comments
 (0)