safe_redirect 0.2.1 → 0.2.2
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.
- 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:
|