cookiefilter 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +93 -0
- data/Rakefile +33 -0
- data/lib/cookiefilter.rb +172 -0
- data/lib/cookiefilter/errors.rb +15 -0
- data/lib/cookiefilter/rules.rb +22 -0
- data/lib/cookiefilter/utils.rb +66 -0
- data/lib/cookiefilter/validator.rb +69 -0
- data/lib/cookiefilter/version.rb +3 -0
- data/lib/tasks/cookiefilter_tasks.rake +4 -0
- metadata +99 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 661342b71d73b5849ad89f06d046a5fceec8d011
|
4
|
+
data.tar.gz: 0eae238747a3364560084e7e3173bf2d5de0a3b6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b01b281d624b06c45693b36fa0e363336ec1be8d65b0cda7cf3b0c33735cc8db149fe9b3d2650a770df0c089f0ead44bfe9996c81a63074bb2922f47012b1790
|
7
|
+
data.tar.gz: 92aaac588a58bacbf263c5e80d3b3cd1abe827df47387c32c5e79173e750bfbbbec93ac35badc01c8504e790f876ddb83a3dc3e48bccf48181c2241d5ef45357
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2017 Stefan Wallin
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
[![Build Status](https://travis-ci.org/StefanWallin/cookiefilter-rails.svg?branch=master)](https://travis-ci.org/StefanWallin/cookiefilter-rails)
|
2
|
+
# Cookiefilter
|
3
|
+
Cookie Filter uses a developer defined safelist of allowed cookies and their
|
4
|
+
values to filter cookies that are not allowed by the safelist configuration.
|
5
|
+
This gem filters both incoming cookies from the browser and what cookies can
|
6
|
+
be set from rails. I want to thank MittMedia DMU for allowing me to open source
|
7
|
+
this piece of code. We are always looking for new developers ;).
|
8
|
+
|
9
|
+
## When would I use this?
|
10
|
+
- If you want to be on top of what data is allowed to be passed to your server.
|
11
|
+
- If you have third party code executing on your first party domain(ads) that set
|
12
|
+
arbitrary cookies.
|
13
|
+
- If your amount and size of cookies can run out of control and exceed the http
|
14
|
+
header limit of 8186 bytes. (At which time certain cloud providers simply
|
15
|
+
interpret that request as an attack and serves back a white page)
|
16
|
+
- If you're already running mod_security or similar web firewalls and need to
|
17
|
+
complement with cookie filtering.
|
18
|
+
|
19
|
+
## Performance
|
20
|
+
Measurment has shown that this filter adds less than 1ms per request.
|
21
|
+
|
22
|
+
This library has been in production on sites with 5 million weekly pageviews
|
23
|
+
for 2 years before being packaged as a gem and open sourced.
|
24
|
+
|
25
|
+
*This gem package has not been tested in production.*
|
26
|
+
|
27
|
+
## Getting started
|
28
|
+
Install the [cookiefilter](http://rubygems.org/StefanWallin/cookiefilter) gem;
|
29
|
+
or add it to your Gemfile with bundler:
|
30
|
+
|
31
|
+
Add this line to your application's `Gemfile`:
|
32
|
+
```ruby
|
33
|
+
gem 'cookiefilter'
|
34
|
+
```
|
35
|
+
|
36
|
+
And then execute:
|
37
|
+
```bash
|
38
|
+
$ bundle install
|
39
|
+
```
|
40
|
+
|
41
|
+
Tell your app to use the Cookiefilter middleware.
|
42
|
+
For Rails 4+ apps:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
# In config/application.rb
|
46
|
+
config.middleware.use Cookiefilter
|
47
|
+
```
|
48
|
+
|
49
|
+
Add a `cookiefilter.rb` file to `config/initializers/`:
|
50
|
+
```ruby
|
51
|
+
# In config/initializers/cookiefilter.rb
|
52
|
+
class Cookiefilter
|
53
|
+
def self.safelist
|
54
|
+
# This is an array of hashes. It serves as a living documentation of our
|
55
|
+
# allowed cookies and their format. Need help with regex? Visit this site:
|
56
|
+
# http://rubular.com/
|
57
|
+
|
58
|
+
# Each hash in the array is per cookie with the following format:
|
59
|
+
# description: Human readable string of what/who this cookie pertains.
|
60
|
+
# key: A regex that matches the name of the cookie or cookies matching
|
61
|
+
# the above description.
|
62
|
+
# value: A regex that validates the content of the cookie, if the regex
|
63
|
+
# is nil, no validation is done.
|
64
|
+
# sacred: This is a boolean indicating that this cookie are not to be
|
65
|
+
# removed to decrease the overall size of cookies per domain.
|
66
|
+
# It will however be removed in second run if no other options
|
67
|
+
# are left.
|
68
|
+
[
|
69
|
+
{
|
70
|
+
description: 'Rails Session Cookie',
|
71
|
+
key: /\Aproject_name_session\z/,
|
72
|
+
value: nil,
|
73
|
+
sacred: true
|
74
|
+
}
|
75
|
+
]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
```
|
79
|
+
|
80
|
+
**Then restart your rails server.**
|
81
|
+
|
82
|
+
Happy filtering!
|
83
|
+
|
84
|
+
## License
|
85
|
+
The gem is available as open source under the terms of the
|
86
|
+
[MIT License](http://opensource.org/licenses/MIT).
|
87
|
+
|
88
|
+
## Contribute
|
89
|
+
All contributions are welcome, issues and PR's.
|
90
|
+
Make sure tests pass by running them like so:
|
91
|
+
```ruby
|
92
|
+
rake test
|
93
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'Cookiefilter'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
require 'bundler/gem_tasks'
|
23
|
+
|
24
|
+
require 'rake/testtask'
|
25
|
+
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
27
|
+
t.libs << 'test'
|
28
|
+
t.pattern = 'test/**/*_test.rb'
|
29
|
+
t.verbose = false
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
task default: :test
|
data/lib/cookiefilter.rb
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
require 'cookiefilter/utils'
|
2
|
+
require 'cookiefilter/rules'
|
3
|
+
require 'cookiefilter/errors'
|
4
|
+
require 'cookiefilter/validator'
|
5
|
+
|
6
|
+
class Cookiefilter
|
7
|
+
class << self
|
8
|
+
def filter_request_cookies(http_cookie)
|
9
|
+
# Flag by replacing with cookie emoji(\u{1F36a}) as a token to identify
|
10
|
+
# and invalidate cookies later on in is_valid_cookie!
|
11
|
+
cookies = Cookiefilter::Utils.sanitize_utf8_string(
|
12
|
+
http_cookie,
|
13
|
+
Cookiefilter::Rules::DISALLOWED_CHARS,
|
14
|
+
Cookiefilter::Rules::INVALID_TOKEN
|
15
|
+
)
|
16
|
+
cookies = Cookiefilter::Utils.parse_request_cookies(cookies)
|
17
|
+
delete, keep = Cookiefilter.validate_request_cookies(cookies)
|
18
|
+
header = Cookiefilter::Utils.construct_request_header(keep)
|
19
|
+
{ delete: delete, keep: keep, header: header.strip }
|
20
|
+
end
|
21
|
+
|
22
|
+
def filter_response_cookies(host, response_header, response_cookies)
|
23
|
+
keep, delete1 = response_cookies[:keep], response_cookies[:delete]
|
24
|
+
cookies = Cookiefilter::Utils.parse_set_cookie_header(response_header)
|
25
|
+
set, delete2 = Cookiefilter.validate_response_cookies(cookies)
|
26
|
+
cookies = Cookiefilter.merge_keep_and_set(keep, set)
|
27
|
+
cookies = Cookiefilter.sort_by_size(cookies)
|
28
|
+
keepers, limited = Cookiefilter.maintain_limits(cookies)
|
29
|
+
set = Cookiefilter.filter_out_keepers(keepers)
|
30
|
+
deleted = Cookiefilter.delete_cookies(delete1 + delete2, limited)
|
31
|
+
Cookiefilter::Utils.construct_response_header(host, deleted + set)
|
32
|
+
end
|
33
|
+
|
34
|
+
def validate_request_cookies(cookies)
|
35
|
+
cookies_to_keep = cookies.select do |cookie|
|
36
|
+
is_valid_cookie!(cookie)
|
37
|
+
end
|
38
|
+
cookies_to_delete = cookies.reject do |cookie|
|
39
|
+
is_valid_cookie!(cookie)
|
40
|
+
end
|
41
|
+
[cookies_to_delete, cookies_to_keep]
|
42
|
+
end
|
43
|
+
|
44
|
+
def validate_response_cookies(cookies)
|
45
|
+
cookies_to_set, cookies_to_delete = [], []
|
46
|
+
cookies.each do |cookie|
|
47
|
+
if is_valid_cookie!(cookie)
|
48
|
+
cookies_to_set << cookie
|
49
|
+
else
|
50
|
+
cookies_to_delete << cookie
|
51
|
+
end
|
52
|
+
end
|
53
|
+
[cookies_to_set, cookies_to_delete]
|
54
|
+
end
|
55
|
+
|
56
|
+
def delete_cookies(blocked, limited)
|
57
|
+
blocked.each do |cookie|
|
58
|
+
delete(cookie)
|
59
|
+
end
|
60
|
+
limited.each do |cookie|
|
61
|
+
delete(cookie)
|
62
|
+
end
|
63
|
+
blocked + limited
|
64
|
+
end
|
65
|
+
|
66
|
+
def delete(cookie)
|
67
|
+
cookie[:options] = ' max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000;'
|
68
|
+
cookie[:value] = 'unset'
|
69
|
+
cookie
|
70
|
+
end
|
71
|
+
|
72
|
+
def merge_keep_and_set(keep, set)
|
73
|
+
keep.each do |keeper|
|
74
|
+
keeper[:type] = :keep
|
75
|
+
end
|
76
|
+
set.each do |setter|
|
77
|
+
setter[:type] = :set
|
78
|
+
end
|
79
|
+
return keep + set
|
80
|
+
end
|
81
|
+
|
82
|
+
def maintain_limits(sized_cookies, kept_large = [], limited = [])
|
83
|
+
if Cookiefilter.cookie_size_too_large?(kept_large, sized_cookies)
|
84
|
+
removed = sized_cookies.shift if sized_cookies.count > 0
|
85
|
+
removed = kept_large.shift if removed.nil?
|
86
|
+
if removed[:sacred] && sized_cookies.count > 0
|
87
|
+
kept_large.push(removed)
|
88
|
+
else
|
89
|
+
limited.push(removed)
|
90
|
+
end
|
91
|
+
return Cookiefilter.maintain_limits(sized_cookies, kept_large, limited)
|
92
|
+
else
|
93
|
+
return [kept_large + sized_cookies, limited]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def filter_out_keepers(keepers)
|
98
|
+
keepers.select { |keeper| keeper[:type] == :set }
|
99
|
+
end
|
100
|
+
|
101
|
+
def sort_by_size(cookies)
|
102
|
+
cookies.sort! do |a, b|
|
103
|
+
b[:size] <=> a[:size]
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def total_cookie_size(keep, set)
|
108
|
+
@size = 0
|
109
|
+
keep.each do |cookie|
|
110
|
+
@size += cookie[:size]
|
111
|
+
end
|
112
|
+
set.each do |cookie|
|
113
|
+
@size += cookie[:size]
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def cookie_size_too_large?(keep, set)
|
118
|
+
Cookiefilter.total_cookie_size(keep, set)
|
119
|
+
@size >= Cookiefilter::Rules::COOKIE_DOMAIN_LIMIT
|
120
|
+
end
|
121
|
+
|
122
|
+
# This method will regex-check both key and value for
|
123
|
+
# this cookie against all safelisted cookies until match
|
124
|
+
# is found.
|
125
|
+
# If a valid match is found, true is returned
|
126
|
+
# Otherwise false is returned.
|
127
|
+
|
128
|
+
def is_valid_cookie!(cookie)
|
129
|
+
return false if "#{cookie[:key]}=#{cookie[:value]}".bytesize > Cookiefilter::Rules::COOKIE_LIMIT
|
130
|
+
return false if /[\u{1F36A}]/.match(cookie[:value])
|
131
|
+
Cookiefilter::Rules::safelist.each do |allowed_cookie|
|
132
|
+
if allowed_cookie[:key].match(cookie[:key])
|
133
|
+
regex = allowed_cookie[:value]
|
134
|
+
|
135
|
+
# Set sacred attribute
|
136
|
+
cookie[:sacred] = allowed_cookie[:sacred]
|
137
|
+
|
138
|
+
# Cookies with nil as value-regex, pass validation.
|
139
|
+
return true if regex.nil?
|
140
|
+
|
141
|
+
return true if regex.match(cookie[:value])
|
142
|
+
|
143
|
+
# Not matching value regex, fail validation.
|
144
|
+
return false
|
145
|
+
end
|
146
|
+
end
|
147
|
+
# Unknown cookie. Log this and fail
|
148
|
+
false
|
149
|
+
end
|
150
|
+
end # end class methods
|
151
|
+
|
152
|
+
def initialize(app)
|
153
|
+
Cookiefilter::Validator.validate_safelist(Cookiefilter::Rules.safelist)
|
154
|
+
@app = app
|
155
|
+
@size = 0
|
156
|
+
end
|
157
|
+
|
158
|
+
# entry point, executes directly after initialize
|
159
|
+
def call(env)
|
160
|
+
result = Cookiefilter.filter_request_cookies(env['HTTP_COOKIE'])
|
161
|
+
env['HTTP_COOKIE'] = result[:header]
|
162
|
+
status, headers, body = @app.call(env)
|
163
|
+
response = Rack::Response.new body, status, headers
|
164
|
+
header = Cookiefilter.filter_response_cookies(
|
165
|
+
env['HTTP_HOST'],
|
166
|
+
response.header['Set-Cookie'],
|
167
|
+
result
|
168
|
+
)
|
169
|
+
response.header['Set-Cookie'] = header
|
170
|
+
response.finish
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Cookiefilter::SafelistMissingError < StandardError
|
2
|
+
def message
|
3
|
+
'Please define your cookie safelist as documented in Readme and then\
|
4
|
+
restart your rails server.'
|
5
|
+
end
|
6
|
+
def backtrace
|
7
|
+
[]
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class Cookiefilter::MalformedSafelistError < StandardError
|
12
|
+
def backtrace
|
13
|
+
[]
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Cookiefilter::Rules
|
2
|
+
COOKIE_DOMAIN_LIMIT = 8186
|
3
|
+
COOKIE_LIMIT = 4093
|
4
|
+
DISALLOWED_CHARS = [
|
5
|
+
"\192", "\193", "\245", "\246", "\247", "\248", "\249",
|
6
|
+
"\250", "\251", "\252", "\253", "\254", "\255"
|
7
|
+
]
|
8
|
+
INVALID_TOKEN = "\u{1F36A}"
|
9
|
+
|
10
|
+
|
11
|
+
def self.method_missing(m, *args, &block)
|
12
|
+
if m.to_sym == :safelist
|
13
|
+
raise Cookiefilter::SafelistMissingError
|
14
|
+
else
|
15
|
+
raise ArgumentError.new("Method `#{m}` doesn't exist.")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.respond_to?(method_name, include_private = false)
|
20
|
+
method_name.to_sym == :safelist || super
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'cookiefilter/errors'
|
2
|
+
|
3
|
+
class Cookiefilter::Utils
|
4
|
+
class << self
|
5
|
+
def sanitize_utf8_string(cookie_string, banned_chars, replace_char)
|
6
|
+
result = ''
|
7
|
+
# blank? can'd handle broken utf-8 characters.
|
8
|
+
return result if cookie_string.nil?
|
9
|
+
cookie_string.each_char do |char|
|
10
|
+
if banned_chars.include? char
|
11
|
+
result << replace_char
|
12
|
+
else
|
13
|
+
result << char
|
14
|
+
end
|
15
|
+
end
|
16
|
+
result
|
17
|
+
end
|
18
|
+
|
19
|
+
def parse_request_cookies(cookie_string)
|
20
|
+
cookies = []
|
21
|
+
return cookies if cookie_string.blank?
|
22
|
+
cookie_strings = cookie_string.split(';')
|
23
|
+
cookie_strings.each do |cookie|
|
24
|
+
key, value = cookie.strip.split('=', 2)
|
25
|
+
cookies << { key: key, value: value, size: "#{key}=#{value}; ".bytesize }
|
26
|
+
end
|
27
|
+
cookies
|
28
|
+
end
|
29
|
+
|
30
|
+
def parse_set_cookie_header(header)
|
31
|
+
cookies = []
|
32
|
+
return cookies if header.blank?
|
33
|
+
header_cookies = header.split("\n")
|
34
|
+
header_cookies.each do |cookie|
|
35
|
+
key, rest = cookie.strip.split('=', 2)
|
36
|
+
value, options = rest.strip.split(';', 2)
|
37
|
+
options = '' if options.nil?
|
38
|
+
size = "#{key}=#{value}; ".bytesize
|
39
|
+
cookies << { key: key, value: value, options: options, size: size }
|
40
|
+
end
|
41
|
+
cookies
|
42
|
+
end
|
43
|
+
|
44
|
+
def construct_request_header(cookies_to_keep)
|
45
|
+
http_cookie = ''
|
46
|
+
cookies_to_keep.each do |cookie|
|
47
|
+
http_cookie << "#{cookie[:key]}=#{cookie[:value]}; "
|
48
|
+
end
|
49
|
+
# Chopping last ';' since headers does not expect it.
|
50
|
+
http_cookie.strip.chomp(';')
|
51
|
+
end
|
52
|
+
|
53
|
+
def construct_response_header(host, set)
|
54
|
+
http_cookies = []
|
55
|
+
naked_host = host.sub!(/\Awww\./, '')
|
56
|
+
set.each do |cookie|
|
57
|
+
http_cookies << "#{cookie[:key]}=#{cookie[:value]};#{cookie[:options]}"
|
58
|
+
if cookie[:value] == 'unset'
|
59
|
+
http_cookies << "#{cookie[:key]}=#{cookie[:value]};Domain=.#{naked_host};#{cookie[:options]}"
|
60
|
+
http_cookies << "#{cookie[:key]}=#{cookie[:value]};Domain=www.#{naked_host};#{cookie[:options]}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
http_cookies.join("\n")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
class Cookiefilter::Validator
|
2
|
+
class << self
|
3
|
+
def validate_safelist(safelist)
|
4
|
+
err = Cookiefilter::MalformedSafelistError
|
5
|
+
Cookiefilter::Validator.validate_array(err, safelist)
|
6
|
+
|
7
|
+
safelist.each_index do |index|
|
8
|
+
obj = safelist[index]
|
9
|
+
Cookiefilter::Validator.validate_hash(err, index, obj)
|
10
|
+
Cookiefilter::Validator.validate_keys(err, index, obj)
|
11
|
+
Cookiefilter::Validator.validate_description(err, index, obj)
|
12
|
+
Cookiefilter::Validator.validate_key(err, index, obj)
|
13
|
+
Cookiefilter::Validator.validate_value(err, index, obj)
|
14
|
+
Cookiefilter::Validator.validate_sacred(err, index, obj)
|
15
|
+
end
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
def validate_array(err, list)
|
20
|
+
raise err, 'safelist method does not return Array' if list.class != Array
|
21
|
+
end
|
22
|
+
|
23
|
+
def validate_hash(err, index, obj)
|
24
|
+
if obj.class != Hash
|
25
|
+
raise err, "safelist child with index #{index}: Is not an Hash Object"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def validate_keys(err, index, obj)
|
30
|
+
%w(description key value sacred).each do |key|
|
31
|
+
unless obj.has_key?(key.to_sym)
|
32
|
+
raise err, "safelist child with index #{index}: Missing key :#{key}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def validate_description(err, index, obj)
|
38
|
+
description = obj[:description]
|
39
|
+
if description.class != String
|
40
|
+
return raise err, "safelist child with index #{index}: ':description' \
|
41
|
+
must be of class String, got #{description.class}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def validate_key(err, index, obj)
|
46
|
+
key = obj[:key]
|
47
|
+
if key.class != Regexp
|
48
|
+
return raise err, "safelist child with index #{index}: ':key' \
|
49
|
+
must be of class Regexp, got #{key.class}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def validate_value(err, index, obj)
|
54
|
+
value = obj[:value]
|
55
|
+
if value.class != Regexp && value.class != NilClass
|
56
|
+
return raise err, "safelist child with index #{index}: ':value' \
|
57
|
+
must be of class Regexp or NilClass, got #{value.class}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def validate_sacred(err, index, obj)
|
62
|
+
sacred = obj[:sacred]
|
63
|
+
if obj[:sacred].class != TrueClass && obj[:sacred].class != FalseClass
|
64
|
+
return raise err, "safelist child with index #{index}: ':sacred' \
|
65
|
+
must be of class TrueClass or FalseClass, got #{sacred.class}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
metadata
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cookiefilter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stefan Wallin
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-11-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 5.1.3
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 5.1.3
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: faker
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: byebug
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: |-
|
56
|
+
Cookie Filter uses a developer defined whitelist of \
|
57
|
+
allowed cookies and their values to filter cookies that do \
|
58
|
+
not live up to the standard.
|
59
|
+
email:
|
60
|
+
- cookiefilter@stefan-wallin.se
|
61
|
+
executables: []
|
62
|
+
extensions: []
|
63
|
+
extra_rdoc_files: []
|
64
|
+
files:
|
65
|
+
- MIT-LICENSE
|
66
|
+
- README.md
|
67
|
+
- Rakefile
|
68
|
+
- lib/cookiefilter.rb
|
69
|
+
- lib/cookiefilter/errors.rb
|
70
|
+
- lib/cookiefilter/rules.rb
|
71
|
+
- lib/cookiefilter/utils.rb
|
72
|
+
- lib/cookiefilter/validator.rb
|
73
|
+
- lib/cookiefilter/version.rb
|
74
|
+
- lib/tasks/cookiefilter_tasks.rake
|
75
|
+
homepage: https://github.com/StefanWallin/cookiefilter
|
76
|
+
licenses:
|
77
|
+
- MIT
|
78
|
+
metadata: {}
|
79
|
+
post_install_message:
|
80
|
+
rdoc_options: []
|
81
|
+
require_paths:
|
82
|
+
- lib
|
83
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
requirements: []
|
94
|
+
rubyforge_project:
|
95
|
+
rubygems_version: 2.6.13
|
96
|
+
signing_key:
|
97
|
+
specification_version: 4
|
98
|
+
summary: Whitelist your users cookies for your domain.
|
99
|
+
test_files: []
|