safe_redirect 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +8 -0
- data/lib/safe_redirect/configuration.rb +10 -1
- data/lib/safe_redirect/safe_redirect.rb +34 -6
- data/lib/safe_redirect/version.rb +1 -1
- data/spec/lib/safe_redirect/configuration_spec.rb +10 -0
- data/spec/lib/safe_redirect/safe_redirect_spec.rb +12 -2
- data/spec/spec_helper.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 73595819096734251288a747c73948f27deb1470
|
4
|
+
data.tar.gz: f1f7de8ed97ee7a9bf50dc7e67d687e896d19e40
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 645b2a52d54d86d5e4e023e511c85ec1fc3ff7f057f25561bb430ebd18708ba0fe158756100171263eb0eedbb4c3c096e7bff26c7ec9cebab8bf3f647e9f897f
|
7
|
+
data.tar.gz: f8fc5d77f0eb82bf925abfcb8d701b690d9f40e007bd8df03f1ae33c89928c6a94b81417d196889d64c21fdd9b4f9ef3ab33fcd49d5d9e9cbb9a2628e73377b1
|
data/README.md
CHANGED
@@ -21,6 +21,14 @@ SafeRedirect.configure do |config|
|
|
21
21
|
end
|
22
22
|
```
|
23
23
|
|
24
|
+
We can also use wildcard subdomain on domain whitelists (thanks to [Mike Campbell](https://github.com/mikecmpbll)).
|
25
|
+
|
26
|
+
```rb
|
27
|
+
SafeRedirect.configure do |config|
|
28
|
+
config.domain_whitelists = ['*.foo.org'] # whitelisting foo.org, m.foo.org, www.foo.org, ...
|
29
|
+
end
|
30
|
+
```
|
31
|
+
|
24
32
|
Add this line to the controllers you wish to secure from open redirection.
|
25
33
|
|
26
34
|
```rb
|
@@ -12,11 +12,20 @@ module SafeRedirect
|
|
12
12
|
end
|
13
13
|
|
14
14
|
class Configuration
|
15
|
-
attr_accessor :default_path
|
15
|
+
attr_accessor :default_path
|
16
|
+
attr_reader :domain_whitelists
|
16
17
|
|
17
18
|
def initialize
|
18
19
|
self.default_path = '/'
|
19
20
|
self.domain_whitelists = []
|
20
21
|
end
|
22
|
+
|
23
|
+
def domain_whitelists=(whitelists)
|
24
|
+
if whitelists.any?{ |w| w =~ /\*\z/ }
|
25
|
+
raise ArgumentError, "whitelisted domain cannot end with a glob (*)"
|
26
|
+
end
|
27
|
+
|
28
|
+
@domain_whitelists = whitelists
|
29
|
+
end
|
21
30
|
end
|
22
31
|
end
|
@@ -3,17 +3,37 @@ require 'uri'
|
|
3
3
|
module SafeRedirect
|
4
4
|
def safe_domain?(uri)
|
5
5
|
return true if uri.host.nil? && uri.scheme.nil?
|
6
|
-
|
6
|
+
return false if uri.host.nil?
|
7
|
+
|
8
|
+
SafeRedirect.configuration.domain_whitelists.any? do |domain|
|
9
|
+
if domain.include?("*")
|
10
|
+
rf = domain.split(/(\*)/).map{ |f| f == "*" ? "\\w*" : Regexp.escape(f) }
|
11
|
+
regexp = Regexp.new("\\A#{rf.join}\\z")
|
12
|
+
|
13
|
+
safe = uri.host.match(regexp)
|
14
|
+
|
15
|
+
# if domain starts with *. and contains no other wildcards, include the
|
16
|
+
# naked domain too (e.g. foo.org when *.foo.org is the whitelist)
|
17
|
+
if domain =~ /\A\*\.[^\*]+\z/
|
18
|
+
naked_domain = domain.gsub("*.", "")
|
19
|
+
safe || uri.host == naked_domain
|
20
|
+
else
|
21
|
+
safe
|
22
|
+
end
|
23
|
+
else
|
24
|
+
uri.host == domain
|
25
|
+
end
|
26
|
+
end
|
7
27
|
end
|
8
28
|
|
9
29
|
def safe_path(path)
|
10
30
|
case path
|
11
31
|
when String
|
12
32
|
clean_path(path)
|
13
|
-
when
|
14
|
-
path
|
33
|
+
when Hash
|
34
|
+
sanitize_hash(path)
|
15
35
|
else
|
16
|
-
|
36
|
+
path
|
17
37
|
end
|
18
38
|
end
|
19
39
|
|
@@ -27,8 +47,16 @@ module SafeRedirect
|
|
27
47
|
|
28
48
|
def clean_path(path)
|
29
49
|
uri = URI.parse(path)
|
30
|
-
safe_domain?(uri) ? path :
|
50
|
+
safe_domain?(uri) ? path : SafeRedirect.configuration.default_path
|
31
51
|
rescue URI::InvalidURIError
|
32
|
-
|
52
|
+
SafeRedirect.configuration.default_path
|
53
|
+
end
|
54
|
+
|
55
|
+
def sanitize_hash(hash)
|
56
|
+
protocol = hash[:protocol] || 'http'
|
57
|
+
host = hash[:host]
|
58
|
+
uri = URI.parse("#{protocol}://#{host}")
|
59
|
+
hash.delete(:host) unless safe_domain?(uri)
|
60
|
+
hash
|
33
61
|
end
|
34
62
|
end
|
@@ -6,6 +6,16 @@ module SafeRedirect
|
|
6
6
|
reset_config
|
7
7
|
end
|
8
8
|
|
9
|
+
it 'errors if you try to end whitelisted domain with glob' do
|
10
|
+
config_update = -> do
|
11
|
+
SafeRedirect.configure do |config|
|
12
|
+
config.domain_whitelists = ["foo.*"]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
expect(config_update).to raise_error(ArgumentError)
|
17
|
+
end
|
18
|
+
|
9
19
|
it 'default default_path is /' do
|
10
20
|
expect(SafeRedirect.configuration.default_path).to eq('/')
|
11
21
|
end
|
@@ -15,8 +15,11 @@ module SafeRedirect
|
|
15
15
|
'/',
|
16
16
|
'/foobar',
|
17
17
|
'http://www.twitter.com',
|
18
|
+
'http://blah.foo.org',
|
19
|
+
'http://foo.org',
|
18
20
|
:back,
|
19
|
-
|
21
|
+
['some', 'object'],
|
22
|
+
{ controller: 'home', action: 'index' },
|
20
23
|
]
|
21
24
|
|
22
25
|
UNSAFE_PATHS = [
|
@@ -26,6 +29,7 @@ module SafeRedirect
|
|
26
29
|
"%@%@%@%@%@%@%@%@%@%@evil.com",
|
27
30
|
"https://www-bukalapak.com",
|
28
31
|
"https://www.bukalapak.com\n.evil.com",
|
32
|
+
"http://blah.blah.foo.org",
|
29
33
|
]
|
30
34
|
|
31
35
|
SAFE_PATHS.each do |path|
|
@@ -36,10 +40,16 @@ module SafeRedirect
|
|
36
40
|
|
37
41
|
UNSAFE_PATHS.each do |path|
|
38
42
|
it "considers #{path} an unsafe path" do
|
39
|
-
expect(Controller.safe_path(path)).to eq(
|
43
|
+
expect(Controller.safe_path(path)).to eq(SafeRedirect.configuration.default_path)
|
40
44
|
end
|
41
45
|
end
|
42
46
|
|
47
|
+
it 'filters host, port, and protocol options when hash is passed to safe_path' do
|
48
|
+
hash = { host: 'yahoo.com', port: 80, protocol: 'https', controller: 'home', action: 'index' }
|
49
|
+
safe_hash = { port: 80, protocol: 'https', controller: 'home', action: 'index' }
|
50
|
+
expect(Controller.safe_path(hash)).to eq(safe_hash)
|
51
|
+
end
|
52
|
+
|
43
53
|
it 'can use redirect_to method with only the target path' do
|
44
54
|
Controller.redirect_to '/'
|
45
55
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -10,7 +10,7 @@ end
|
|
10
10
|
def load_config
|
11
11
|
SafeRedirect.configure do |config|
|
12
12
|
config.default_path = '/sdsdkkk'
|
13
|
-
config.domain_whitelists =
|
13
|
+
config.domain_whitelists = %w{www.twitter.com www.bukalapak.com *.foo.org}
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: safe_redirect
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Edwin Tunggawan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-08-
|
11
|
+
date: 2016-08-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -71,3 +71,4 @@ test_files:
|
|
71
71
|
- spec/lib/safe_redirect/configuration_spec.rb
|
72
72
|
- spec/lib/safe_redirect/safe_redirect_spec.rb
|
73
73
|
- spec/spec_helper.rb
|
74
|
+
has_rdoc:
|