secure_headers 3.6.7 → 3.7.0
Sign up to get free protection for your applications and to get access to all the features.
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
|