http-security 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rspec +1 -0
- data/.travis.yml +21 -0
- data/.yardopts +1 -0
- data/ChangeLog.md +17 -0
- data/Gemfile +17 -0
- data/LICENSE.txt +20 -0
- data/README.md +90 -0
- data/Rakefile +34 -0
- data/http-security.gemspec +23 -0
- data/lib/http/security.rb +2 -0
- data/lib/http/security/exceptions.rb +8 -0
- data/lib/http/security/headers.rb +12 -0
- data/lib/http/security/headers/cache_control.rb +36 -0
- data/lib/http/security/headers/content_security_policy.rb +71 -0
- data/lib/http/security/headers/content_security_policy_report_only.rb +10 -0
- data/lib/http/security/headers/pragma.rb +24 -0
- data/lib/http/security/headers/public_key_pins.rb +60 -0
- data/lib/http/security/headers/public_key_pins_report_only.rb +10 -0
- data/lib/http/security/headers/set_cookie.rb +75 -0
- data/lib/http/security/headers/strict_transport_security.rb +29 -0
- data/lib/http/security/headers/x_content_type_options.rb +24 -0
- data/lib/http/security/headers/x_frame_options.rb +39 -0
- data/lib/http/security/headers/x_permitted_cross_domain_policies.rb +47 -0
- data/lib/http/security/headers/x_xss_protection.rb +34 -0
- data/lib/http/security/http_date.rb +13 -0
- data/lib/http/security/malformed_header.rb +33 -0
- data/lib/http/security/parsers.rb +14 -0
- data/lib/http/security/parsers/cache_control.rb +62 -0
- data/lib/http/security/parsers/content_security_policy.rb +128 -0
- data/lib/http/security/parsers/content_security_policy_report_only.rb +10 -0
- data/lib/http/security/parsers/expires.rb +19 -0
- data/lib/http/security/parsers/parser.rb +408 -0
- data/lib/http/security/parsers/pragma.rb +25 -0
- data/lib/http/security/parsers/public_key_pins.rb +43 -0
- data/lib/http/security/parsers/public_key_pins_report_only.rb +10 -0
- data/lib/http/security/parsers/set_cookie.rb +62 -0
- data/lib/http/security/parsers/strict_transport_security.rb +42 -0
- data/lib/http/security/parsers/x_content_type_options.rb +19 -0
- data/lib/http/security/parsers/x_frame_options.rb +47 -0
- data/lib/http/security/parsers/x_permitted_cross_domain_policies.rb +33 -0
- data/lib/http/security/parsers/x_xss_protection.rb +27 -0
- data/lib/http/security/response.rb +323 -0
- data/lib/http/security/version.rb +5 -0
- data/spec/data/alexa.csv +100 -0
- data/spec/headers/cache_control_spec.rb +40 -0
- data/spec/headers/content_security_policy_spec.rb +46 -0
- data/spec/headers/pragma_spec.rb +26 -0
- data/spec/headers/public_key_pins_spec.rb +68 -0
- data/spec/headers/set_cookie_spec.rb +122 -0
- data/spec/headers/strict_transport_security_spec.rb +39 -0
- data/spec/headers/x_content_type_options_spec.rb +26 -0
- data/spec/headers/x_frame_options_spec.rb +86 -0
- data/spec/headers/x_permitted_cross_domain_policies_spec.rb +108 -0
- data/spec/headers/x_xss_protection_spec.rb +59 -0
- data/spec/parsers/cache_control_spec.rb +26 -0
- data/spec/parsers/content_security_policy_report_only_spec.rb +48 -0
- data/spec/parsers/content_security_policy_spec.rb +74 -0
- data/spec/parsers/expires_spec.rb +71 -0
- data/spec/parsers/parser_spec.rb +317 -0
- data/spec/parsers/pragma_spec.rb +10 -0
- data/spec/parsers/public_key_pins_spec.rb +81 -0
- data/spec/parsers/set_cookie_spec.rb +55 -0
- data/spec/parsers/strict_transport_security_spec.rb +62 -0
- data/spec/parsers/x_content_type_options_spec.rb +10 -0
- data/spec/parsers/x_frame_options_spec.rb +24 -0
- data/spec/parsers/x_permitted_cross_domain_policies_spec.rb +34 -0
- data/spec/parsers/x_xss_protection_spec.rb +39 -0
- data/spec/response_spec.rb +262 -0
- data/spec/spec_helper.rb +13 -0
- data/tasks/alexa.rb +40 -0
- metadata +171 -0
data/spec/data/alexa.csv
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
1,Google.com
|
2
|
+
2,Facebook.com
|
3
|
+
3,Youtube.com
|
4
|
+
4,Yahoo.com
|
5
|
+
5,Baidu.com
|
6
|
+
6,Wikipedia.org
|
7
|
+
7,Amazon.com
|
8
|
+
8,Twitter.com
|
9
|
+
9,Taobao.com
|
10
|
+
10,Qq.com
|
11
|
+
11,Google.co.in
|
12
|
+
12,Live.com
|
13
|
+
13,Linkedin.com
|
14
|
+
14,Sina.com.cn
|
15
|
+
15,Hao123.com
|
16
|
+
16,Weibo.com
|
17
|
+
17,Blogspot.com
|
18
|
+
18,Yahoo.co.jp
|
19
|
+
19,Tmall.com
|
20
|
+
20,Yandex.ru
|
21
|
+
21,Vk.com
|
22
|
+
22,Ebay.com
|
23
|
+
23,Google.de
|
24
|
+
24,Sohu.com
|
25
|
+
25,Bing.com
|
26
|
+
26,Ask.com
|
27
|
+
27,Wordpress.com
|
28
|
+
28,Pinterest.com
|
29
|
+
29,360.cn
|
30
|
+
30,Google.co.uk
|
31
|
+
31,Msn.com
|
32
|
+
32,Google.co.jp
|
33
|
+
33,Instagram.com
|
34
|
+
34,Reddit.com
|
35
|
+
35,Tumblr.com
|
36
|
+
36,Google.fr
|
37
|
+
37,Apple.com
|
38
|
+
38,Google.com.br
|
39
|
+
39,Mail.ru
|
40
|
+
40,Imgur.com
|
41
|
+
41,Xvideos.com
|
42
|
+
42,163.com
|
43
|
+
43,Paypal.com
|
44
|
+
44,Google.ru
|
45
|
+
45,Microsoft.com
|
46
|
+
46,Alibaba.com
|
47
|
+
47,Soso.com
|
48
|
+
48,Adcash.com
|
49
|
+
49,Aliexpress.com
|
50
|
+
50,T.co
|
51
|
+
51,Google.it
|
52
|
+
52,Imdb.com
|
53
|
+
53,Amazon.co.jp
|
54
|
+
54,Go.com
|
55
|
+
55,Google.es
|
56
|
+
56,Craigslist.org
|
57
|
+
57,Stackoverflow.com
|
58
|
+
58,Xhamster.com
|
59
|
+
59,Amazon.de
|
60
|
+
60,Fc2.com
|
61
|
+
61,Google.ca
|
62
|
+
62,Espn.go.com
|
63
|
+
63,Google.com.mx
|
64
|
+
64,Onclickads.net
|
65
|
+
65,Akamaihd.net
|
66
|
+
66,Netflix.com
|
67
|
+
67,Flipkart.com
|
68
|
+
68,Gmw.cn
|
69
|
+
69,Cnn.com
|
70
|
+
70,Bbc.co.uk
|
71
|
+
71,Adobe.com
|
72
|
+
72,Google.com.hk
|
73
|
+
73,Google.com.tr
|
74
|
+
74,Amazon.co.uk
|
75
|
+
75,Pornhub.com
|
76
|
+
76,Huffingtonpost.com
|
77
|
+
77,Dropbox.com
|
78
|
+
78,Ebay.de
|
79
|
+
79,Google.com.au
|
80
|
+
80,Google.pl
|
81
|
+
81,Kickass.to
|
82
|
+
82,Odnoklassniki.ru
|
83
|
+
83,Googleusercontent.com
|
84
|
+
84,Dailymotion.com
|
85
|
+
85,Blogger.com
|
86
|
+
86,People.com.cn
|
87
|
+
87,Rakuten.co.jp
|
88
|
+
88,Amazon.in
|
89
|
+
89,Thepiratebay.se
|
90
|
+
90,Naver.com
|
91
|
+
91,Xnxx.com
|
92
|
+
92,Nytimes.com
|
93
|
+
93,Xinhuanet.com
|
94
|
+
94,Buzzfeed.com
|
95
|
+
95,Pixnet.net
|
96
|
+
96,Alipay.com
|
97
|
+
97,Indiatimes.com
|
98
|
+
98,Ebay.co.uk
|
99
|
+
99,Outbrain.com
|
100
|
+
100,Dailymail.co.uk
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'http/security/headers/cache_control'
|
3
|
+
|
4
|
+
describe HTTP::Security::Headers::CacheControl do
|
5
|
+
let(:max_age) { 0 }
|
6
|
+
|
7
|
+
subject do
|
8
|
+
described_class.new(
|
9
|
+
private: true,
|
10
|
+
max_age: max_age,
|
11
|
+
no_cache: true
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#initialize" do
|
16
|
+
it "should set max_age" do
|
17
|
+
expect(subject.max_age).to be == max_age
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#private?" do
|
22
|
+
context "when private: is true" do
|
23
|
+
subject { described_class.new(private: true) }
|
24
|
+
|
25
|
+
it { expect(subject.private?).to be(true) }
|
26
|
+
end
|
27
|
+
|
28
|
+
context "when private: is false" do
|
29
|
+
subject { described_class.new(private: false) }
|
30
|
+
|
31
|
+
it { expect(subject.private?).to be(false) }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#to_s" do
|
36
|
+
it "should return a comma separated list of directives" do
|
37
|
+
expect(subject.to_s).to be == "private, max-age=#{max_age}, no-cache"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'http/security/headers/content_security_policy'
|
3
|
+
|
4
|
+
describe HTTP::Security::Headers::ContentSecurityPolicy do
|
5
|
+
let(:default_src) { "'self'" }
|
6
|
+
let(:img_src) { '*' }
|
7
|
+
let(:object_src) { 'media1.example.com media2.example.com *.cdn.example.com' }
|
8
|
+
let(:script_src) { 'trustedscripts.example.com' }
|
9
|
+
|
10
|
+
subject do
|
11
|
+
described_class.new(
|
12
|
+
default_src: default_src,
|
13
|
+
img_src: img_src,
|
14
|
+
object_src: object_src,
|
15
|
+
script_src: script_src
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#initialize" do
|
20
|
+
it "should set default_src"
|
21
|
+
it "should set script_src"
|
22
|
+
it "should set object_src"
|
23
|
+
it "should set style_src"
|
24
|
+
it "should set img_src"
|
25
|
+
it "should set media_src"
|
26
|
+
it "should set frame_src"
|
27
|
+
it "should set font_src"
|
28
|
+
it "should set connect_src"
|
29
|
+
|
30
|
+
context "when report_uri: is omitted" do
|
31
|
+
subject { described_class.new() }
|
32
|
+
|
33
|
+
it "should default it to []" do
|
34
|
+
expect(subject.report_uri).to be == []
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should set sandbox"
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#to_s" do
|
42
|
+
it "should return a semicolon separated list of directives" do
|
43
|
+
expect(subject.to_s).to be == "default-src #{default_src}; script-src #{script_src}; object-src #{object_src}; img-src #{img_src}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'http/security/headers/pragma'
|
3
|
+
|
4
|
+
describe HTTP::Security::Headers::Pragma do
|
5
|
+
subject { described_class.new(no_cache: true) }
|
6
|
+
|
7
|
+
describe "no_cache?" do
|
8
|
+
context "when no_cache: was true" do
|
9
|
+
subject { described_class.new(no_cache: true) }
|
10
|
+
|
11
|
+
it { expect(subject.no_cache?).to be true }
|
12
|
+
end
|
13
|
+
|
14
|
+
context "when no_cache: was false" do
|
15
|
+
subject { described_class.new(no_cache: false) }
|
16
|
+
|
17
|
+
it { expect(subject.no_cache?).to be false }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#to_s" do
|
22
|
+
it "should return a string" do
|
23
|
+
expect(subject.to_s).to be == "no-cache"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'http/security/headers/public_key_pins'
|
3
|
+
|
4
|
+
require 'uri'
|
5
|
+
|
6
|
+
describe HTTP::Security::Headers::PublicKeyPins do
|
7
|
+
let(:pin_sha256) do
|
8
|
+
[
|
9
|
+
'klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=',
|
10
|
+
'M8HztCzM3elUxkcjR2S5P4hhyBNf6lHkmjAHKhpGPWE='
|
11
|
+
]
|
12
|
+
end
|
13
|
+
let(:pin_sha9000) { 'jlkfsjlksjlkfsjfs' }
|
14
|
+
let(:max_age) { 31536000 }
|
15
|
+
let(:include_sub_domains) { true }
|
16
|
+
let(:report_uri) { URI('https://www.example.com/') }
|
17
|
+
let(:strict) { true }
|
18
|
+
|
19
|
+
subject do
|
20
|
+
described_class.new(
|
21
|
+
pin_sha256: pin_sha256,
|
22
|
+
'pin-sha9000' => pin_sha9000,
|
23
|
+
max_age: max_age,
|
24
|
+
includesubdomains: include_sub_domains,
|
25
|
+
report_uri: report_uri,
|
26
|
+
strict: strict
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#initialize" do
|
31
|
+
it "should group together pin options" do
|
32
|
+
expect(subject.pin).to be == {
|
33
|
+
sha256: pin_sha256,
|
34
|
+
'sha9000' => [pin_sha9000]
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should set max_age" do
|
39
|
+
expect(subject.max_age).to be max_age
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should set include_sub_domains" do
|
43
|
+
expect(subject.include_sub_domains?).to be include_sub_domains
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should set report_uri" do
|
47
|
+
expect(subject.report_uri).to be report_uri
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should set strict" do
|
51
|
+
expect(subject.strict?).to be strict
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "#to_s" do
|
56
|
+
it "should return a semicolon separated list of directives" do
|
57
|
+
expect(subject.to_s).to be == [
|
58
|
+
"pin-sha256=\"#{pin_sha256[0]}\"",
|
59
|
+
"pin-sha256=\"#{pin_sha256[1]}\"",
|
60
|
+
"pin-sha9000=\"#{pin_sha9000}\"",
|
61
|
+
"max-age=#{max_age}",
|
62
|
+
"includeSubdomains",
|
63
|
+
"report-uri=\"#{report_uri}\"",
|
64
|
+
"strict"
|
65
|
+
].join('; ')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'http/security/headers/set_cookie'
|
3
|
+
|
4
|
+
require 'date'
|
5
|
+
|
6
|
+
describe HTTP::Security::Headers::SetCookie do
|
7
|
+
let(:path) { '/accounts' }
|
8
|
+
let(:expires) { Date.parse("Wed, 09 Jun 2021 10:18:14 GMT") }
|
9
|
+
let(:secure) { 'Secure' }
|
10
|
+
let(:domain) { '.example.com' }
|
11
|
+
let(:http_only) { 'HttpOnly' }
|
12
|
+
|
13
|
+
describe described_class::Cookie do
|
14
|
+
let(:name) { :foo }
|
15
|
+
let(:value) { 'bar' }
|
16
|
+
|
17
|
+
subject do
|
18
|
+
described_class.new(
|
19
|
+
cookie: {name => value},
|
20
|
+
path: path,
|
21
|
+
expires: expires,
|
22
|
+
secure: secure,
|
23
|
+
domain: domain,
|
24
|
+
http_only: http_only
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#initialize" do
|
29
|
+
it "should set cookie" do
|
30
|
+
expect(subject.cookie).to be == {name => value}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#name" do
|
35
|
+
it "should return the name" do
|
36
|
+
expect(subject.name).to be == name
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#value" do
|
41
|
+
it "should return the value" do
|
42
|
+
expect(subject.value).to be == value
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#secure?" do
|
47
|
+
context "when secure: was present" do
|
48
|
+
subject { described_class.new(secure: 'Secure') }
|
49
|
+
|
50
|
+
it { expect(subject.secure?).to be true}
|
51
|
+
end
|
52
|
+
|
53
|
+
context "when secure: was not present" do
|
54
|
+
subject { described_class.new() }
|
55
|
+
|
56
|
+
it { expect(subject.secure?).to be false }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "#http_only?" do
|
61
|
+
context "when http_only: was present" do
|
62
|
+
subject { described_class.new(http_only: 'HttpOnly') }
|
63
|
+
|
64
|
+
it { expect(subject.http_only?).to be true}
|
65
|
+
end
|
66
|
+
|
67
|
+
context "when http_only: was not present" do
|
68
|
+
subject { described_class.new() }
|
69
|
+
|
70
|
+
it { expect(subject.http_only?).to be false }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "#to_s" do
|
75
|
+
it "should format the cookie" do
|
76
|
+
expect(subject.to_s).to be == "#{name}=#{value}; Path=#{path}; Domain=#{domain}; Expires=#{expires.httpdate}; #{secure}; #{http_only}"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
let(:cookies) do
|
82
|
+
[
|
83
|
+
{
|
84
|
+
cookie: {foo: 'bar'},
|
85
|
+
path: path,
|
86
|
+
domain: domain,
|
87
|
+
secure: secure,
|
88
|
+
http_only: http_only
|
89
|
+
},
|
90
|
+
|
91
|
+
{
|
92
|
+
cookie: {bar: 'baz'},
|
93
|
+
domain: domain,
|
94
|
+
path: path,
|
95
|
+
expires: expires
|
96
|
+
}
|
97
|
+
]
|
98
|
+
end
|
99
|
+
|
100
|
+
subject { described_class.new(cookies) }
|
101
|
+
|
102
|
+
describe "#initialize" do
|
103
|
+
it "should set cookies" do
|
104
|
+
expect(subject.cookies.length).to be == cookies.length
|
105
|
+
expect(subject.cookies).to all(be_kind_of(described_class::Cookie))
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "#each" do
|
110
|
+
it "should enumerate over each cookie" do
|
111
|
+
expect { |b|
|
112
|
+
subject.each(&b)
|
113
|
+
}.to yield_successive_args(*subject.cookies)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "#to_s" do
|
118
|
+
it "should return a semicolon separated list of directives" do
|
119
|
+
expect(subject.to_s).to be == "foo=bar; Path=#{path}; Domain=#{domain}; Secure; HttpOnly, bar=baz; Path=#{path}; Domain=#{domain}; Expires=#{expires.httpdate}"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'http/security/headers/strict_transport_security'
|
3
|
+
|
4
|
+
describe HTTP::Security::Headers::StrictTransportSecurity do
|
5
|
+
let(:max_age) { 31536000 }
|
6
|
+
|
7
|
+
subject do
|
8
|
+
described_class.new(
|
9
|
+
max_age: max_age,
|
10
|
+
includesubdomains: true
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#initialize" do
|
15
|
+
it "should set max_age" do
|
16
|
+
expect(subject.max_age).to be == max_age
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#include_sub_domains?" do
|
21
|
+
context "when includesubdomains: was true" do
|
22
|
+
subject { described_class.new(includesubdomains: true) }
|
23
|
+
|
24
|
+
it { expect(subject.include_sub_domains?).to be true }
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when includesubdomains: was false" do
|
28
|
+
subject { described_class.new(includesubdomains: false) }
|
29
|
+
|
30
|
+
it { expect(subject.include_sub_domains?).to be false }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#to_s" do
|
35
|
+
it "should return a string" do
|
36
|
+
expect(subject.to_s).to be == "max-age=#{max_age}; includeSubDomains"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|