rack-protection 1.2.0 → 1.3.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rack-protection might be problematic. Click here for more details.
- data/README.md +2 -22
- data/lib/rack/protection.rb +2 -0
- data/lib/rack/protection/base.rb +11 -1
- data/lib/rack/protection/escaped_params.rb +1 -1
- data/lib/rack/protection/frame_options.rb +6 -1
- data/lib/rack/protection/http_origin.rb +32 -0
- data/lib/rack/protection/json_csrf.rb +1 -1
- data/lib/rack/protection/path_traversal.rb +1 -1
- data/lib/rack/protection/session_hijacking.rb +2 -1
- data/lib/rack/protection/version.rb +1 -1
- data/lib/rack/protection/xss_header.rb +9 -3
- data/rack-protection.gemspec +25 -5
- data/spec/escaped_params_spec.rb +10 -0
- data/spec/frame_options_spec.rb +19 -4
- data/spec/http_origin_spec.rb +38 -0
- data/spec/json_csrf_spec.rb +8 -0
- data/spec/protection_spec.rb +17 -0
- data/spec/session_hijacking_spec.rb +14 -0
- data/spec/spec_helper.rb +2 -1
- data/spec/xss_header_spec.rb +29 -3
- metadata +47 -11
data/README.md
CHANGED
@@ -43,12 +43,13 @@ Prevented by:
|
|
43
43
|
* `Rack::Protection::JsonCsrf`
|
44
44
|
* `Rack::Protection::RemoteReferrer` (not included by `use Rack::Protection`)
|
45
45
|
* `Rack::Protection::RemoteToken`
|
46
|
+
* `Rack::Protection::HttpOrigin`
|
46
47
|
|
47
48
|
## Cross Site Scripting
|
48
49
|
|
49
50
|
Prevented by:
|
50
51
|
|
51
|
-
* `Rack::Protection::EscapedParams`
|
52
|
+
* `Rack::Protection::EscapedParams` (not included by `use Rack::Protection`)
|
52
53
|
* `Rack::Protection::XssHeader` (Internet Explorer only)
|
53
54
|
|
54
55
|
## Clickjacking
|
@@ -79,24 +80,3 @@ Prevented by:
|
|
79
80
|
|
80
81
|
gem install rack-protection
|
81
82
|
|
82
|
-
# History
|
83
|
-
|
84
|
-
## v0.1.0 (2011/06/20)
|
85
|
-
|
86
|
-
First public release.
|
87
|
-
|
88
|
-
## v1.0.0 (2011/09/02)
|
89
|
-
|
90
|
-
First stable release.
|
91
|
-
|
92
|
-
Changes:
|
93
|
-
|
94
|
-
* Fix bug in JsonCsrf
|
95
|
-
|
96
|
-
## v1.1.0 (2011/09/03)
|
97
|
-
|
98
|
-
Second public release.
|
99
|
-
|
100
|
-
Changes:
|
101
|
-
|
102
|
-
* Dependency on `escape_utils` is now optional
|
data/lib/rack/protection.rb
CHANGED
@@ -8,6 +8,7 @@ module Rack
|
|
8
8
|
autoload :EscapedParams, 'rack/protection/escaped_params'
|
9
9
|
autoload :FormToken, 'rack/protection/form_token'
|
10
10
|
autoload :FrameOptions, 'rack/protection/frame_options'
|
11
|
+
autoload :HttpOrigin, 'rack/protection/http_origin'
|
11
12
|
autoload :IPSpoofing, 'rack/protection/ip_spoofing'
|
12
13
|
autoload :JsonCsrf, 'rack/protection/json_csrf'
|
13
14
|
autoload :PathTraversal, 'rack/protection/path_traversal'
|
@@ -21,6 +22,7 @@ module Rack
|
|
21
22
|
except = Array options[:except]
|
22
23
|
Rack::Builder.new do
|
23
24
|
use ::Rack::Protection::FrameOptions, options unless except.include? :frame_options
|
25
|
+
use ::Rack::Protection::HttpOrigin, options unless except.include? :http_origin
|
24
26
|
use ::Rack::Protection::IPSpoofing, options unless except.include? :ip_spoofing
|
25
27
|
use ::Rack::Protection::JsonCsrf, options unless except.include? :json_csrf
|
26
28
|
use ::Rack::Protection::PathTraversal, options unless except.include? :path_traversal
|
data/lib/rack/protection/base.rb
CHANGED
@@ -10,7 +10,8 @@ module Rack
|
|
10
10
|
:reaction => :default_reaction, :logging => true,
|
11
11
|
:message => 'Forbidden', :encryptor => Digest::SHA1,
|
12
12
|
:session_key => 'rack.session', :status => 403,
|
13
|
-
:allow_empty_referrer => true
|
13
|
+
:allow_empty_referrer => true,
|
14
|
+
:html_types => %w[text/html application/xhtml]
|
14
15
|
}
|
15
16
|
|
16
17
|
attr_reader :app, :options
|
@@ -81,6 +82,10 @@ module Rack
|
|
81
82
|
URI.parse(ref).host || Request.new(env).host
|
82
83
|
end
|
83
84
|
|
85
|
+
def origin(env)
|
86
|
+
env['HTTP_ORIGIN'] || env['HTTP_X_ORIGIN']
|
87
|
+
end
|
88
|
+
|
84
89
|
def random_string(secure = defined? SecureRandom)
|
85
90
|
secure ? SecureRandom.hex(32) : "%032x" % rand(2**128-1)
|
86
91
|
rescue NotImplementedError
|
@@ -92,6 +97,11 @@ module Rack
|
|
92
97
|
end
|
93
98
|
|
94
99
|
alias default_reaction deny
|
100
|
+
|
101
|
+
def html?(headers)
|
102
|
+
return false unless header = headers.detect { |k,v| k.downcase == 'content-type' }
|
103
|
+
options[:html_types].include? header.last[/^\w+\/\w+/]
|
104
|
+
end
|
95
105
|
end
|
96
106
|
end
|
97
107
|
end
|
@@ -18,8 +18,13 @@ module Rack
|
|
18
18
|
# to allow embedding from the same origin (default).
|
19
19
|
class FrameOptions < XSSHeader
|
20
20
|
default_options :frame_options => :sameorigin
|
21
|
+
|
21
22
|
def header
|
22
|
-
|
23
|
+
@header ||= begin
|
24
|
+
frame_options = options[:frame_options]
|
25
|
+
frame_options = options[:frame_options].to_s.upcase unless frame_options.respond_to? :to_str
|
26
|
+
{ 'X-Frame-Options' => frame_options.to_str }
|
27
|
+
end
|
23
28
|
end
|
24
29
|
end
|
25
30
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'rack/protection'
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
module Protection
|
5
|
+
##
|
6
|
+
# Prevented attack:: CSRF
|
7
|
+
# Supported browsers:: Google Chrome 2, Safari 4 and later
|
8
|
+
# More infos:: http://en.wikipedia.org/wiki/Cross-site_request_forgery
|
9
|
+
# http://tools.ietf.org/html/draft-abarth-origin
|
10
|
+
#
|
11
|
+
# Does not accept unsafe HTTP requests when value of Origin HTTP request header
|
12
|
+
# does not match default or whitelisted URIs.
|
13
|
+
class HttpOrigin < Base
|
14
|
+
default_reaction :deny
|
15
|
+
|
16
|
+
def accepts?(env)
|
17
|
+
# only for unsafe request methods
|
18
|
+
safe?(env) and return true
|
19
|
+
# ignore if origin is not set
|
20
|
+
origin = env['HTTP_ORIGIN'] or return true
|
21
|
+
|
22
|
+
# check base url
|
23
|
+
Request.new(env).base_url == origin and return true
|
24
|
+
|
25
|
+
# check whitelist
|
26
|
+
options[:origin_whitelist] or return false
|
27
|
+
options[:origin_whitelist].include?(origin)
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -16,7 +16,7 @@ module Rack
|
|
16
16
|
def call(env)
|
17
17
|
status, headers, body = app.call(env)
|
18
18
|
if headers['Content-Type'].to_s.split(';', 2).first =~ /^\s*application\/json\s*$/
|
19
|
-
if referrer(env) != Request.new(env).host
|
19
|
+
if origin(env).nil? and referrer(env) != Request.new(env).host
|
20
20
|
result = react(env)
|
21
21
|
warn env, "attack prevented by #{self.class}"
|
22
22
|
end
|
@@ -12,7 +12,7 @@ module Rack
|
|
12
12
|
class PathTraversal < Base
|
13
13
|
def call(env)
|
14
14
|
path_was = env["PATH_INFO"]
|
15
|
-
env["PATH_INFO"] = cleanup path_was if path_was
|
15
|
+
env["PATH_INFO"] = cleanup path_was if path_was && !path_was.empty?
|
16
16
|
app.call env
|
17
17
|
ensure
|
18
18
|
env["PATH_INFO"] = path_was
|
@@ -12,15 +12,21 @@ module Rack
|
|
12
12
|
# Options:
|
13
13
|
# xss_mode:: How the browser should prevent the attack (default: :block)
|
14
14
|
class XSSHeader < Base
|
15
|
-
default_options :xss_mode => :block
|
15
|
+
default_options :xss_mode => :block, :nosniff => true
|
16
16
|
|
17
17
|
def header
|
18
|
-
|
18
|
+
headers = {
|
19
|
+
'X-XSS-Protection' => "1; mode=#{options[:xss_mode]}",
|
20
|
+
'X-Content-Type-Options' => "nosniff"
|
21
|
+
}
|
22
|
+
headers.delete("X-Content-Type-Options") unless options[:nosniff]
|
23
|
+
headers
|
19
24
|
end
|
20
25
|
|
21
26
|
def call(env)
|
22
27
|
status, headers, body = @app.call(env)
|
23
|
-
|
28
|
+
headers = header.merge(headers) if options[:nosniff] and html?(headers)
|
29
|
+
[status, headers, body]
|
24
30
|
end
|
25
31
|
end
|
26
32
|
end
|
data/rack-protection.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
Gem::Specification.new do |s|
|
3
3
|
# general infos
|
4
4
|
s.name = "rack-protection"
|
5
|
-
s.version = "1.
|
5
|
+
s.version = "1.3.1"
|
6
6
|
s.description = "You should use protection!"
|
7
7
|
s.homepage = "http://github.com/rkh/rack-protection"
|
8
8
|
s.summary = s.description
|
@@ -10,21 +10,39 @@ Gem::Specification.new do |s|
|
|
10
10
|
# generated from git shortlog -sn
|
11
11
|
s.authors = [
|
12
12
|
"Konstantin Haase",
|
13
|
-
"
|
13
|
+
"Alex Rodionov",
|
14
|
+
"Chris Heald",
|
15
|
+
"Chris Mytton",
|
14
16
|
"Corey Ward",
|
15
17
|
"David Kellum",
|
16
18
|
"Fojas",
|
17
|
-
"
|
19
|
+
"Mael Clerambault",
|
20
|
+
"Martin Mauch",
|
21
|
+
"SAKAI, Kazuaki",
|
22
|
+
"Stanislav Savulchik",
|
23
|
+
"Steve Agalloco",
|
24
|
+
"Akzhan Abdulin",
|
25
|
+
"TOBY",
|
26
|
+
"Bjørge Næss"
|
18
27
|
]
|
19
28
|
|
20
29
|
# generated from git shortlog -sne
|
21
30
|
s.email = [
|
22
31
|
"konstantin.mailinglists@googlemail.com",
|
23
|
-
"
|
32
|
+
"p0deje@gmail.com",
|
33
|
+
"cheald@gmail.com",
|
34
|
+
"self@hecticjeff.net",
|
24
35
|
"coreyward@me.com",
|
25
36
|
"dek-oss@gravitext.com",
|
26
37
|
"developer@fojasaur.us",
|
27
|
-
"
|
38
|
+
"mael@clerambault.fr",
|
39
|
+
"martin.mauch@gmail.com",
|
40
|
+
"kaz.july.7@gmail.com",
|
41
|
+
"s.savulchik@gmail.com",
|
42
|
+
"steve.agalloco@gmail.com",
|
43
|
+
"akzhan.abdulin@gmail.com",
|
44
|
+
"toby.net.info.mail+git@gmail.com",
|
45
|
+
"bjoerge@bengler.no"
|
28
46
|
]
|
29
47
|
|
30
48
|
# generated from git ls-files
|
@@ -39,6 +57,7 @@ Gem::Specification.new do |s|
|
|
39
57
|
"lib/rack/protection/escaped_params.rb",
|
40
58
|
"lib/rack/protection/form_token.rb",
|
41
59
|
"lib/rack/protection/frame_options.rb",
|
60
|
+
"lib/rack/protection/http_origin.rb",
|
42
61
|
"lib/rack/protection/ip_spoofing.rb",
|
43
62
|
"lib/rack/protection/json_csrf.rb",
|
44
63
|
"lib/rack/protection/path_traversal.rb",
|
@@ -52,6 +71,7 @@ Gem::Specification.new do |s|
|
|
52
71
|
"spec/escaped_params_spec.rb",
|
53
72
|
"spec/form_token_spec.rb",
|
54
73
|
"spec/frame_options_spec.rb",
|
74
|
+
"spec/http_origin_spec.rb",
|
55
75
|
"spec/ip_spoofing_spec.rb",
|
56
76
|
"spec/json_csrf_spec.rb",
|
57
77
|
"spec/path_traversal_spec.rb",
|
data/spec/escaped_params_spec.rb
CHANGED
@@ -30,5 +30,15 @@ describe Rack::Protection::EscapedParams do
|
|
30
30
|
get '/', :foo => {:bar => "<bar>"}
|
31
31
|
body.should == '<bar>'
|
32
32
|
end
|
33
|
+
|
34
|
+
it 'leaves cache-breaker params untouched' do
|
35
|
+
mock_app do |env|
|
36
|
+
request = Rack::Request.new(env)
|
37
|
+
[200, {'Content-Type' => 'text/plain'}, ['hi']]
|
38
|
+
end
|
39
|
+
|
40
|
+
get '/?95df8d9bf5237ad08df3115ee74dcb10'
|
41
|
+
body.should == 'hi'
|
42
|
+
end
|
33
43
|
end
|
34
44
|
end
|
data/spec/frame_options_spec.rb
CHANGED
@@ -3,8 +3,12 @@ require File.expand_path('../spec_helper.rb', __FILE__)
|
|
3
3
|
describe Rack::Protection::FrameOptions do
|
4
4
|
it_behaves_like "any rack application"
|
5
5
|
|
6
|
-
it 'should set the X-
|
7
|
-
get('/').headers["X-Frame-Options"].should == "
|
6
|
+
it 'should set the X-Frame-Options' do
|
7
|
+
get('/', {}, 'wants' => 'text/html').headers["X-Frame-Options"].should == "SAMEORIGIN"
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should not set the X-Frame-Options for other content types' do
|
11
|
+
get('/', {}, 'wants' => 'text/foo').headers["X-Frame-Options"].should be_nil
|
8
12
|
end
|
9
13
|
|
10
14
|
it 'should allow changing the protection mode' do
|
@@ -14,11 +18,22 @@ describe Rack::Protection::FrameOptions do
|
|
14
18
|
run DummyApp
|
15
19
|
end
|
16
20
|
|
17
|
-
get('/').headers["X-Frame-Options"].should == "
|
21
|
+
get('/', {}, 'wants' => 'text/html').headers["X-Frame-Options"].should == "DENY"
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
it 'should allow changing the protection mode to a string' do
|
26
|
+
# I have no clue what other modes are available
|
27
|
+
mock_app do
|
28
|
+
use Rack::Protection::FrameOptions, :frame_options => "ALLOW-FROM foo"
|
29
|
+
run DummyApp
|
30
|
+
end
|
31
|
+
|
32
|
+
get('/', {}, 'wants' => 'text/html').headers["X-Frame-Options"].should == "ALLOW-FROM foo"
|
18
33
|
end
|
19
34
|
|
20
35
|
it 'should not override the header if already set' do
|
21
36
|
mock_app with_headers("X-Frame-Options" => "allow")
|
22
|
-
get('/').headers["X-Frame-Options"].should == "allow"
|
37
|
+
get('/', {}, 'wants' => 'text/html').headers["X-Frame-Options"].should == "allow"
|
23
38
|
end
|
24
39
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.expand_path('../spec_helper.rb', __FILE__)
|
2
|
+
|
3
|
+
describe Rack::Protection::HttpOrigin do
|
4
|
+
it_behaves_like "any rack application"
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
mock_app do
|
8
|
+
use Rack::Protection::HttpOrigin
|
9
|
+
run DummyApp
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
%w(GET HEAD POST PUT DELETE).each do |method|
|
14
|
+
it "accepts #{method} requests with no Origin" do
|
15
|
+
send(method.downcase, '/').should be_ok
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
%w(GET HEAD).each do |method|
|
20
|
+
it "accepts #{method} requests with non-whitelisted Origin" do
|
21
|
+
send(method.downcase, '/', {}, 'HTTP_ORIGIN' => 'http://malicious.com').should be_ok
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
%w(POST PUT DELETE).each do |method|
|
26
|
+
it "denies #{method} requests with non-whitelisted Origin" do
|
27
|
+
send(method.downcase, '/', {}, 'HTTP_ORIGIN' => 'http://malicious.com').should_not be_ok
|
28
|
+
end
|
29
|
+
|
30
|
+
it "accepts #{method} requests with whitelisted Origin" do
|
31
|
+
mock_app do
|
32
|
+
use Rack::Protection::HttpOrigin, :origin_whitelist => ['http://www.friend.com']
|
33
|
+
run DummyApp
|
34
|
+
end
|
35
|
+
send(method.downcase, '/', {}, 'HTTP_ORIGIN' => 'http://www.friend.com').should be_ok
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/spec/json_csrf_spec.rb
CHANGED
@@ -12,6 +12,14 @@ describe Rack::Protection::JsonCsrf do
|
|
12
12
|
get('/', {}, 'HTTP_REFERER' => 'http://evil.com').should_not be_ok
|
13
13
|
end
|
14
14
|
|
15
|
+
it "accepts requests with json responses with a remote referrer when there's an origin header set" do
|
16
|
+
get('/', {}, 'HTTP_REFERER' => 'http://good.com', 'HTTP_ORIGIN' => 'http://good.com').should be_ok
|
17
|
+
end
|
18
|
+
|
19
|
+
it "accepts requests with json responses with a remote referrer when there's an x-origin header set" do
|
20
|
+
get('/', {}, 'HTTP_REFERER' => 'http://good.com', 'HTTP_X_ORIGIN' => 'http://good.com').should be_ok
|
21
|
+
end
|
22
|
+
|
15
23
|
it "accepts get requests with json responses with a local referrer" do
|
16
24
|
get('/', {}, 'HTTP_REFERER' => '/').should be_ok
|
17
25
|
end
|
data/spec/protection_spec.rb
CHANGED
@@ -17,4 +17,21 @@ describe Rack::Protection do
|
|
17
17
|
get '/', {}, 'rack.session' => session, 'HTTP_FOO' => 'BAR'
|
18
18
|
session.should be_empty
|
19
19
|
end
|
20
|
+
|
21
|
+
describe "#html?" do
|
22
|
+
context "given an appropriate content-type header" do
|
23
|
+
subject { Rack::Protection::Base.new(nil).html? 'content-type' => "text/html" }
|
24
|
+
it { should be_true }
|
25
|
+
end
|
26
|
+
|
27
|
+
context "given an inappropriate content-type header" do
|
28
|
+
subject { Rack::Protection::Base.new(nil).html? 'content-type' => "image/gif" }
|
29
|
+
it { should be_false }
|
30
|
+
end
|
31
|
+
|
32
|
+
context "given no content-type header" do
|
33
|
+
subject { Rack::Protection::Base.new(nil).html?({}) }
|
34
|
+
it { should be_false }
|
35
|
+
end
|
36
|
+
end
|
20
37
|
end
|
@@ -31,6 +31,20 @@ describe Rack::Protection::SessionHijacking do
|
|
31
31
|
session.should be_empty
|
32
32
|
end
|
33
33
|
|
34
|
+
it "accepts requests with the same Accept-Language header" do
|
35
|
+
session = {:foo => :bar}
|
36
|
+
get '/', {}, 'rack.session' => session, 'HTTP_ACCEPT_LANGUAGE' => 'a'
|
37
|
+
get '/', {}, 'rack.session' => session, 'HTTP_ACCEPT_LANGUAGE' => 'a'
|
38
|
+
session.should_not be_empty
|
39
|
+
end
|
40
|
+
|
41
|
+
it "comparison of Accept-Language header is not case sensitive" do
|
42
|
+
session = {:foo => :bar}
|
43
|
+
get '/', {}, 'rack.session' => session, 'HTTP_ACCEPT_LANGUAGE' => 'a'
|
44
|
+
get '/', {}, 'rack.session' => session, 'HTTP_ACCEPT_LANGUAGE' => 'A'
|
45
|
+
session.should_not be_empty
|
46
|
+
end
|
47
|
+
|
34
48
|
it "accepts requests with a changing Version header"do
|
35
49
|
session = {:foo => :bar}
|
36
50
|
get '/', {}, 'rack.session' => session, 'HTTP_VERSION' => '1.0'
|
data/spec/spec_helper.rb
CHANGED
@@ -24,7 +24,8 @@ end
|
|
24
24
|
module DummyApp
|
25
25
|
def self.call(env)
|
26
26
|
Thread.current[:last_env] = env
|
27
|
-
[
|
27
|
+
body = (env['REQUEST_METHOD'] == 'HEAD' ? '' : 'ok')
|
28
|
+
[200, {'Content-Type' => env['wants'] || 'text/plain'}, [body]]
|
28
29
|
end
|
29
30
|
end
|
30
31
|
|
data/spec/xss_header_spec.rb
CHANGED
@@ -4,7 +4,15 @@ describe Rack::Protection::XSSHeader do
|
|
4
4
|
it_behaves_like "any rack application"
|
5
5
|
|
6
6
|
it 'should set the X-XSS-Protection' do
|
7
|
-
get('/').headers["X-XSS-Protection"].should == "1; mode=block"
|
7
|
+
get('/', {}, 'wants' => 'text/html;charset=utf-8').headers["X-XSS-Protection"].should == "1; mode=block"
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should set the X-XSS-Protection for XHTML' do
|
11
|
+
get('/', {}, 'wants' => 'application/xhtml+xml').headers["X-XSS-Protection"].should == "1; mode=block"
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should not set the X-XSS-Protection for other content types' do
|
15
|
+
get('/', {}, 'wants' => 'application/foo').headers["X-XSS-Protection"].should be_nil
|
8
16
|
end
|
9
17
|
|
10
18
|
it 'should allow changing the protection mode' do
|
@@ -14,11 +22,29 @@ describe Rack::Protection::XSSHeader do
|
|
14
22
|
run DummyApp
|
15
23
|
end
|
16
24
|
|
17
|
-
get('/').headers["X-XSS-Protection"].should == "1; mode=foo"
|
25
|
+
get('/', {}, 'wants' => 'application/xhtml').headers["X-XSS-Protection"].should == "1; mode=foo"
|
18
26
|
end
|
19
27
|
|
20
28
|
it 'should not override the header if already set' do
|
21
29
|
mock_app with_headers("X-XSS-Protection" => "0")
|
22
|
-
get('/').headers["X-XSS-Protection"].should == "0"
|
30
|
+
get('/', {}, 'wants' => 'text/html').headers["X-XSS-Protection"].should == "0"
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should set the X-Content-Type-Options' do
|
34
|
+
get('/', {}, 'wants' => 'text/html').header["X-Content-Type-Options"].should == "nosniff"
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should allow changing the nosniff-mode off' do
|
38
|
+
mock_app do
|
39
|
+
use Rack::Protection::XSSHeader, :nosniff => false
|
40
|
+
run DummyApp
|
41
|
+
end
|
42
|
+
|
43
|
+
get('/').headers["X-Content-Type-Options"].should be_nil
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should not override the header if already set X-Content-Type-Options' do
|
47
|
+
mock_app with_headers("X-Content-Type-Options" => "sniff")
|
48
|
+
get('/', {}, 'wants' => 'text/html').headers["X-Content-Type-Options"].should == "sniff"
|
23
49
|
end
|
24
50
|
end
|
metadata
CHANGED
@@ -1,24 +1,33 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-protection
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Konstantin Haase
|
9
|
-
-
|
9
|
+
- Alex Rodionov
|
10
|
+
- Chris Heald
|
11
|
+
- Chris Mytton
|
10
12
|
- Corey Ward
|
11
13
|
- David Kellum
|
12
14
|
- Fojas
|
15
|
+
- Mael Clerambault
|
13
16
|
- Martin Mauch
|
17
|
+
- SAKAI, Kazuaki
|
18
|
+
- Stanislav Savulchik
|
19
|
+
- Steve Agalloco
|
20
|
+
- Akzhan Abdulin
|
21
|
+
- TOBY
|
22
|
+
- Bjørge Næss
|
14
23
|
autorequire:
|
15
24
|
bindir: bin
|
16
25
|
cert_chain: []
|
17
|
-
date:
|
26
|
+
date: 2012-12-10 00:00:00.000000000 Z
|
18
27
|
dependencies:
|
19
28
|
- !ruby/object:Gem::Dependency
|
20
29
|
name: rack
|
21
|
-
requirement:
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
22
31
|
none: false
|
23
32
|
requirements:
|
24
33
|
- - ! '>='
|
@@ -26,10 +35,15 @@ dependencies:
|
|
26
35
|
version: '0'
|
27
36
|
type: :runtime
|
28
37
|
prerelease: false
|
29
|
-
version_requirements:
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
30
44
|
- !ruby/object:Gem::Dependency
|
31
45
|
name: rack-test
|
32
|
-
requirement:
|
46
|
+
requirement: !ruby/object:Gem::Requirement
|
33
47
|
none: false
|
34
48
|
requirements:
|
35
49
|
- - ! '>='
|
@@ -37,10 +51,15 @@ dependencies:
|
|
37
51
|
version: '0'
|
38
52
|
type: :development
|
39
53
|
prerelease: false
|
40
|
-
version_requirements:
|
54
|
+
version_requirements: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ! '>='
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
41
60
|
- !ruby/object:Gem::Dependency
|
42
61
|
name: rspec
|
43
|
-
requirement:
|
62
|
+
requirement: !ruby/object:Gem::Requirement
|
44
63
|
none: false
|
45
64
|
requirements:
|
46
65
|
- - ~>
|
@@ -48,15 +67,29 @@ dependencies:
|
|
48
67
|
version: '2.0'
|
49
68
|
type: :development
|
50
69
|
prerelease: false
|
51
|
-
version_requirements:
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '2.0'
|
52
76
|
description: You should use protection!
|
53
77
|
email:
|
54
78
|
- konstantin.mailinglists@googlemail.com
|
55
|
-
-
|
79
|
+
- p0deje@gmail.com
|
80
|
+
- cheald@gmail.com
|
81
|
+
- self@hecticjeff.net
|
56
82
|
- coreyward@me.com
|
57
83
|
- dek-oss@gravitext.com
|
58
84
|
- developer@fojasaur.us
|
85
|
+
- mael@clerambault.fr
|
59
86
|
- martin.mauch@gmail.com
|
87
|
+
- kaz.july.7@gmail.com
|
88
|
+
- s.savulchik@gmail.com
|
89
|
+
- steve.agalloco@gmail.com
|
90
|
+
- akzhan.abdulin@gmail.com
|
91
|
+
- toby.net.info.mail+git@gmail.com
|
92
|
+
- bjoerge@bengler.no
|
60
93
|
executables: []
|
61
94
|
extensions: []
|
62
95
|
extra_rdoc_files: []
|
@@ -71,6 +104,7 @@ files:
|
|
71
104
|
- lib/rack/protection/escaped_params.rb
|
72
105
|
- lib/rack/protection/form_token.rb
|
73
106
|
- lib/rack/protection/frame_options.rb
|
107
|
+
- lib/rack/protection/http_origin.rb
|
74
108
|
- lib/rack/protection/ip_spoofing.rb
|
75
109
|
- lib/rack/protection/json_csrf.rb
|
76
110
|
- lib/rack/protection/path_traversal.rb
|
@@ -84,6 +118,7 @@ files:
|
|
84
118
|
- spec/escaped_params_spec.rb
|
85
119
|
- spec/form_token_spec.rb
|
86
120
|
- spec/frame_options_spec.rb
|
121
|
+
- spec/http_origin_spec.rb
|
87
122
|
- spec/ip_spoofing_spec.rb
|
88
123
|
- spec/json_csrf_spec.rb
|
89
124
|
- spec/path_traversal_spec.rb
|
@@ -113,8 +148,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
113
148
|
version: '0'
|
114
149
|
requirements: []
|
115
150
|
rubyforge_project:
|
116
|
-
rubygems_version: 1.8.
|
151
|
+
rubygems_version: 1.8.23
|
117
152
|
signing_key:
|
118
153
|
specification_version: 3
|
119
154
|
summary: You should use protection!
|
120
155
|
test_files: []
|
156
|
+
has_rdoc:
|