secure_headers 3.6.7 → 3.7.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.
Potentially problematic release.
This version of secure_headers might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +6 -0
- data/lib/secure_headers/configuration.rb +4 -1
- data/lib/secure_headers/headers/expect_certificate_transparency.rb +70 -0
- data/lib/secure_headers.rb +2 -0
- data/secure_headers.gemspec +1 -1
- data/spec/lib/secure_headers/headers/expect_certificate_spec.rb +42 -0
- data/spec/spec_helper.rb +1 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 591de0f41bc64b3520fbb2fdab9fc94b490d1604
|
4
|
+
data.tar.gz: f836c5e63e4d054ff2ce3f1ec597bbd9cf67ed4b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5317d425d7c65dfc73b32703aae7e16e3a566b620b42e3233cd6dc7403a1a9842bb7dc00ffc5c13a86240c5a8abee3ae07fed0c73d4b06a06bcc11db39a79a20
|
7
|
+
data.tar.gz: 154573bfb9112b4b1510abbde3f5eb1e85b709f7839ff4a6a547223e67e698ff014bb578f02b0e8775ee723016f5903e8cda38cb9846b24cafe3dc8e414bb007
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -18,6 +18,7 @@ The gem will automatically apply several headers that are related to security.
|
|
18
18
|
- 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)
|
19
19
|
- Referrer-Policy - [Referrer Policy draft](https://w3c.github.io/webappsec-referrer-policy/)
|
20
20
|
- Public Key Pinning - Pin certificate fingerprints in the browser to prevent man-in-the-middle attacks due to compromised Certificate Authorities. [Public Key Pinning Specification](https://tools.ietf.org/html/rfc7469)
|
21
|
+
- 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/).
|
21
22
|
- Clear-Site-Data - Clearing browser data for origin. [Clear-Site-Data specification](https://w3c.github.io/webappsec-clear-site-data/).
|
22
23
|
|
23
24
|
It can also mark all http cookies with the Secure, HttpOnly and SameSite attributes (when configured to do so).
|
@@ -76,6 +77,11 @@ SecureHeaders::Configuration.default do |config|
|
|
76
77
|
"storage",
|
77
78
|
"executionContexts"
|
78
79
|
]
|
80
|
+
config.expect_certificate_transparency = {
|
81
|
+
enforce: false,
|
82
|
+
max_age: 1.day.to_i,
|
83
|
+
report_uri: "https://report-uri.io/example-ct"
|
84
|
+
}
|
79
85
|
config.csp = {
|
80
86
|
# "meta" values. these will shaped the header, but the values are not included in the header.
|
81
87
|
# report_only: true, # default: false [DEPRECATED from 3.5.0: instead, configure csp_report_only]
|
@@ -116,7 +116,7 @@ module SecureHeaders
|
|
116
116
|
|
117
117
|
attr_writer :hsts, :x_frame_options, :x_content_type_options,
|
118
118
|
:x_xss_protection, :x_download_options, :x_permitted_cross_domain_policies,
|
119
|
-
:referrer_policy, :clear_site_data
|
119
|
+
:referrer_policy, :clear_site_data, :expect_certificate_transparency
|
120
120
|
|
121
121
|
attr_reader :cached_headers, :csp, :cookies, :csp_report_only, :hpkp, :hpkp_report_host
|
122
122
|
|
@@ -143,6 +143,7 @@ module SecureHeaders
|
|
143
143
|
@x_frame_options = nil
|
144
144
|
@x_permitted_cross_domain_policies = nil
|
145
145
|
@x_xss_protection = nil
|
146
|
+
@expect_certificate_transparency = nil
|
146
147
|
|
147
148
|
self.hpkp = OPT_OUT
|
148
149
|
self.referrer_policy = OPT_OUT
|
@@ -168,6 +169,7 @@ module SecureHeaders
|
|
168
169
|
copy.x_download_options = @x_download_options
|
169
170
|
copy.x_permitted_cross_domain_policies = @x_permitted_cross_domain_policies
|
170
171
|
copy.clear_site_data = @clear_site_data
|
172
|
+
copy.expect_certificate_transparency = @expect_certificate_transparency
|
171
173
|
copy.referrer_policy = @referrer_policy
|
172
174
|
copy.hpkp = @hpkp
|
173
175
|
copy.hpkp_report_host = @hpkp_report_host
|
@@ -200,6 +202,7 @@ module SecureHeaders
|
|
200
202
|
XDownloadOptions.validate_config!(@x_download_options)
|
201
203
|
XPermittedCrossDomainPolicies.validate_config!(@x_permitted_cross_domain_policies)
|
202
204
|
ClearSiteData.validate_config!(@clear_site_data)
|
205
|
+
ExpectCertificateTransparency.validate_config!(@expect_certificate_transparency)
|
203
206
|
PublicKeyPins.validate_config!(@hpkp)
|
204
207
|
Cookie.validate_config!(@cookies)
|
205
208
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module SecureHeaders
|
3
|
+
class ExpectCertificateTransparencyConfigError < StandardError; end
|
4
|
+
|
5
|
+
class ExpectCertificateTransparency
|
6
|
+
HEADER_NAME = "Expect-CT".freeze
|
7
|
+
CONFIG_KEY = :expect_certificate_transparency
|
8
|
+
INVALID_CONFIGURATION_ERROR = "config must be a hash.".freeze
|
9
|
+
INVALID_ENFORCE_VALUE_ERROR = "enforce must be a boolean".freeze
|
10
|
+
REQUIRED_MAX_AGE_ERROR = "max-age is a required directive.".freeze
|
11
|
+
INVALID_MAX_AGE_ERROR = "max-age must be a number.".freeze
|
12
|
+
|
13
|
+
class << self
|
14
|
+
# Public: Generate a Expect-CT header.
|
15
|
+
#
|
16
|
+
# Returns nil if not configured, returns header name and value if
|
17
|
+
# configured.
|
18
|
+
def make_header(config)
|
19
|
+
return if config.nil?
|
20
|
+
|
21
|
+
header = new(config)
|
22
|
+
[HEADER_NAME, header.value]
|
23
|
+
end
|
24
|
+
|
25
|
+
def validate_config!(config)
|
26
|
+
return if config.nil? || config == OPT_OUT
|
27
|
+
raise ExpectCertificateTransparencyConfigError.new(INVALID_CONFIGURATION_ERROR) unless config.is_a? Hash
|
28
|
+
|
29
|
+
unless [true, false, nil].include?(config[:enforce])
|
30
|
+
raise ExpectCertificateTransparencyConfigError.new(INVALID_ENFORCE_VALUE_ERROR)
|
31
|
+
end
|
32
|
+
|
33
|
+
if !config[:max_age]
|
34
|
+
raise ExpectCertificateTransparencyConfigError.new(REQUIRED_MAX_AGE_ERROR)
|
35
|
+
elsif config[:max_age].to_s !~ /\A\d+\z/
|
36
|
+
raise ExpectCertificateTransparencyConfigError.new(INVALID_MAX_AGE_ERROR)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def initialize(config)
|
42
|
+
@enforced = config.fetch(:enforce, nil)
|
43
|
+
@max_age = config.fetch(:max_age, nil)
|
44
|
+
@report_uri = config.fetch(:report_uri, nil)
|
45
|
+
end
|
46
|
+
|
47
|
+
def value
|
48
|
+
header_value = [
|
49
|
+
enforced_directive,
|
50
|
+
max_age_directive,
|
51
|
+
report_uri_directive
|
52
|
+
].compact.join("; ").strip
|
53
|
+
end
|
54
|
+
|
55
|
+
def enforced_directive
|
56
|
+
# Unfortunately `if @enforced` isn't enough here in case someone
|
57
|
+
# passes in a random string so let's be specific with it to prevent
|
58
|
+
# accidental enforcement.
|
59
|
+
"enforce" if @enforced == true
|
60
|
+
end
|
61
|
+
|
62
|
+
def max_age_directive
|
63
|
+
"max-age=#{@max_age}" if @max_age
|
64
|
+
end
|
65
|
+
|
66
|
+
def report_uri_directive
|
67
|
+
"report-uri=\"#{@report_uri}\"" if @report_uri
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/secure_headers.rb
CHANGED
@@ -11,6 +11,7 @@ require "secure_headers/headers/x_download_options"
|
|
11
11
|
require "secure_headers/headers/x_permitted_cross_domain_policies"
|
12
12
|
require "secure_headers/headers/referrer_policy"
|
13
13
|
require "secure_headers/headers/clear_site_data"
|
14
|
+
require "secure_headers/headers/expect_certificate_transparency"
|
14
15
|
require "secure_headers/middleware"
|
15
16
|
require "secure_headers/railtie"
|
16
17
|
require "secure_headers/view_helper"
|
@@ -51,6 +52,7 @@ module SecureHeaders
|
|
51
52
|
CSP = ContentSecurityPolicy
|
52
53
|
|
53
54
|
ALL_HEADER_CLASSES = [
|
55
|
+
ExpectCertificateTransparency,
|
54
56
|
ClearSiteData,
|
55
57
|
ContentSecurityPolicyConfig,
|
56
58
|
ContentSecurityPolicyReportOnlyConfig,
|
data/secure_headers.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
Gem::Specification.new do |gem|
|
3
3
|
gem.name = "secure_headers"
|
4
|
-
gem.version = "3.
|
4
|
+
gem.version = "3.7.0"
|
5
5
|
gem.authors = ["Neil Matatall"]
|
6
6
|
gem.email = ["neil.matatall@gmail.com"]
|
7
7
|
gem.description = 'Manages application of security headers with many safe defaults.'
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
module SecureHeaders
|
5
|
+
describe ExpectCertificateTransparency do
|
6
|
+
specify { expect(ExpectCertificateTransparency.new(max_age: 1234, enforce: true).value).to eq("enforce; max-age=1234") }
|
7
|
+
specify { expect(ExpectCertificateTransparency.new(max_age: 1234, enforce: false).value).to eq("max-age=1234") }
|
8
|
+
specify { expect(ExpectCertificateTransparency.new(max_age: 1234, enforce: "yolocopter").value).to eq("max-age=1234") }
|
9
|
+
specify { expect(ExpectCertificateTransparency.new(max_age: 1234, report_uri: "https://report-uri.io/expect-ct").value).to eq("max-age=1234; report-uri=\"https://report-uri.io/expect-ct\"") }
|
10
|
+
specify do
|
11
|
+
config = { enforce: true, max_age: 1234, report_uri: "https://report-uri.io/expect-ct" }
|
12
|
+
header_value = "enforce; max-age=1234; report-uri=\"https://report-uri.io/expect-ct\""
|
13
|
+
expect(ExpectCertificateTransparency.new(config).value).to eq(header_value)
|
14
|
+
end
|
15
|
+
|
16
|
+
context "with an invalid configuration" do
|
17
|
+
it "raises an exception when configuration isn't a hash" do
|
18
|
+
expect do
|
19
|
+
ExpectCertificateTransparency.validate_config!(%w(a))
|
20
|
+
end.to raise_error(ExpectCertificateTransparencyConfigError)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "raises an exception when max-age is not provided" do
|
24
|
+
expect do
|
25
|
+
ExpectCertificateTransparency.validate_config!(foo: "bar")
|
26
|
+
end.to raise_error(ExpectCertificateTransparencyConfigError)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "raises an exception with an invalid max-age" do
|
30
|
+
expect do
|
31
|
+
ExpectCertificateTransparency.validate_config!(max_age: "abc123")
|
32
|
+
end.to raise_error(ExpectCertificateTransparencyConfigError)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "raises an exception with an invalid enforce value" do
|
36
|
+
expect do
|
37
|
+
ExpectCertificateTransparency.validate_config!(enforce: "brokenstring")
|
38
|
+
end.to raise_error(ExpectCertificateTransparencyConfigError)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -34,6 +34,7 @@ def expect_default_values(hash)
|
|
34
34
|
expect(hash[SecureHeaders::XContentTypeOptions::HEADER_NAME]).to eq(SecureHeaders::XContentTypeOptions::DEFAULT_VALUE)
|
35
35
|
expect(hash[SecureHeaders::XPermittedCrossDomainPolicies::HEADER_NAME]).to eq(SecureHeaders::XPermittedCrossDomainPolicies::DEFAULT_VALUE)
|
36
36
|
expect(hash[SecureHeaders::ReferrerPolicy::HEADER_NAME]).to be_nil
|
37
|
+
expect(hash[SecureHeaders::ExpectCertificateTransparency::HEADER_NAME]).to be_nil
|
37
38
|
end
|
38
39
|
|
39
40
|
module SecureHeaders
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: secure_headers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Neil Matatall
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-08-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -73,6 +73,7 @@ files:
|
|
73
73
|
- lib/secure_headers/headers/content_security_policy.rb
|
74
74
|
- lib/secure_headers/headers/content_security_policy_config.rb
|
75
75
|
- lib/secure_headers/headers/cookie.rb
|
76
|
+
- lib/secure_headers/headers/expect_certificate_transparency.rb
|
76
77
|
- lib/secure_headers/headers/policy_management.rb
|
77
78
|
- lib/secure_headers/headers/public_key_pins.rb
|
78
79
|
- lib/secure_headers/headers/referrer_policy.rb
|
@@ -92,6 +93,7 @@ files:
|
|
92
93
|
- spec/lib/secure_headers/headers/clear_site_data_spec.rb
|
93
94
|
- spec/lib/secure_headers/headers/content_security_policy_spec.rb
|
94
95
|
- spec/lib/secure_headers/headers/cookie_spec.rb
|
96
|
+
- spec/lib/secure_headers/headers/expect_certificate_spec.rb
|
95
97
|
- spec/lib/secure_headers/headers/policy_management_spec.rb
|
96
98
|
- spec/lib/secure_headers/headers/public_key_pins_spec.rb
|
97
99
|
- spec/lib/secure_headers/headers/referrer_policy_spec.rb
|
@@ -136,6 +138,7 @@ test_files:
|
|
136
138
|
- spec/lib/secure_headers/headers/clear_site_data_spec.rb
|
137
139
|
- spec/lib/secure_headers/headers/content_security_policy_spec.rb
|
138
140
|
- spec/lib/secure_headers/headers/cookie_spec.rb
|
141
|
+
- spec/lib/secure_headers/headers/expect_certificate_spec.rb
|
139
142
|
- spec/lib/secure_headers/headers/policy_management_spec.rb
|
140
143
|
- spec/lib/secure_headers/headers/public_key_pins_spec.rb
|
141
144
|
- spec/lib/secure_headers/headers/referrer_policy_spec.rb
|