Class: Rack::LibInjection::Config
- Inherits:
-
Data
- Object
- Data
- Rack::LibInjection::Config
- Defined in:
- lib/rack/libinjection.rb
Instance Attribute Summary collapse
-
#detect_mask ⇒ Object
readonly
Returns the value of attribute detect_mask.
-
#ignore_headers ⇒ Object
readonly
Returns the value of attribute ignore_headers.
-
#ignore_headers_lookup ⇒ Object
readonly
Returns the value of attribute ignore_headers_lookup.
-
#ignore_params ⇒ Object
readonly
Returns the value of attribute ignore_params.
-
#ignore_params_lookup ⇒ Object
readonly
Returns the value of attribute ignore_params_lookup.
-
#max_depth ⇒ Object
readonly
Returns the value of attribute max_depth.
-
#max_value_bytes ⇒ Object
readonly
Returns the value of attribute max_value_bytes.
-
#mode ⇒ Object
readonly
Returns the value of attribute mode.
-
#notifier ⇒ Object
readonly
Returns the value of attribute notifier.
-
#notifier_errors ⇒ Object
readonly
Returns the value of attribute notifier_errors.
-
#notify_skipped ⇒ Object
readonly
Returns the value of attribute notify_skipped.
-
#parser_errors ⇒ Object
readonly
Returns the value of attribute parser_errors.
-
#path_decode_depth ⇒ Object
readonly
Returns the value of attribute path_decode_depth.
-
#scan ⇒ Object
readonly
Returns the value of attribute scan.
-
#scan_cookie_names ⇒ Object
readonly
Returns the value of attribute scan_cookie_names.
-
#scan_sqli ⇒ Object
readonly
Returns the value of attribute scan_sqli.
-
#scan_xss ⇒ Object
readonly
Returns the value of attribute scan_xss.
-
#skipped_inputs ⇒ Object
readonly
Returns the value of attribute skipped_inputs.
-
#threats ⇒ Object
readonly
Returns the value of attribute threats.
Class Method Summary collapse
- .bounded_non_negative_integer!(value, name, max) ⇒ Object
- .build(mode: :report, scan: DEFAULT_SCAN, threats: DEFAULT_THREATS, ignore_params: DEFAULT_IGNORE_PARAMS, ignore_headers: DEFAULT_IGNORE_HEADERS, scan_cookie_names: false, max_value_bytes: DEFAULT_MAX_VALUE_BYTES, max_depth: DEFAULT_MAX_DEPTH, path_decode_depth: DEFAULT_PATH_DECODE_DEPTH, parser_errors: :auto, notifier: nil, logger: nil, notifier_errors: :ignore, notify_skipped: true, skipped_inputs: :auto) ⇒ Object
- .build_notifier(logger) ⇒ Object
- .detect_mask_for(threats) ⇒ Object
- .lookup_for(values) ⇒ Object
- .non_negative_integer!(value, name) ⇒ Object
- .normalize_header_names(values) ⇒ Object
- .normalize_param_names(values) ⇒ Object
- .positive_integer!(value, name) ⇒ Object
- .validate_mode(value) ⇒ Object
- .validate_notifier_errors(value) ⇒ Object
- .validate_parser_errors(value) ⇒ Object
- .validate_scan(value) ⇒ Object
- .validate_skipped_inputs(value) ⇒ Object
- .validate_threats(value) ⇒ Object
Instance Method Summary collapse
- #env_only_scan? ⇒ Boolean
- #ignore_header?(normalized_key) ⇒ Boolean
- #ignore_param?(key) ⇒ Boolean
- #notifier_active? ⇒ Boolean
- #parser_error_policy ⇒ Object
- #scan_both_threats? ⇒ Boolean
- #scan_cookies? ⇒ Boolean
- #scan_headers? ⇒ Boolean
- #scan_params? ⇒ Boolean
- #scan_path? ⇒ Boolean
- #scan_query? ⇒ Boolean
- #skipped_input_policy ⇒ Object
Instance Attribute Details
#detect_mask ⇒ Object (readonly)
Returns the value of attribute detect_mask
68 69 70 |
# File 'lib/rack/libinjection.rb', line 68 def detect_mask @detect_mask end |
#ignore_headers ⇒ Object (readonly)
Returns the value of attribute ignore_headers
68 69 70 |
# File 'lib/rack/libinjection.rb', line 68 def ignore_headers @ignore_headers end |
#ignore_headers_lookup ⇒ Object (readonly)
Returns the value of attribute ignore_headers_lookup
68 69 70 |
# File 'lib/rack/libinjection.rb', line 68 def ignore_headers_lookup @ignore_headers_lookup end |
#ignore_params ⇒ Object (readonly)
Returns the value of attribute ignore_params
68 69 70 |
# File 'lib/rack/libinjection.rb', line 68 def ignore_params @ignore_params end |
#ignore_params_lookup ⇒ Object (readonly)
Returns the value of attribute ignore_params_lookup
68 69 70 |
# File 'lib/rack/libinjection.rb', line 68 def ignore_params_lookup @ignore_params_lookup end |
#max_depth ⇒ Object (readonly)
Returns the value of attribute max_depth
68 69 70 |
# File 'lib/rack/libinjection.rb', line 68 def max_depth @max_depth end |
#max_value_bytes ⇒ Object (readonly)
Returns the value of attribute max_value_bytes
68 69 70 |
# File 'lib/rack/libinjection.rb', line 68 def max_value_bytes @max_value_bytes end |
#mode ⇒ Object (readonly)
Returns the value of attribute mode
68 69 70 |
# File 'lib/rack/libinjection.rb', line 68 def mode @mode end |
#notifier ⇒ Object (readonly)
Returns the value of attribute notifier
68 69 70 |
# File 'lib/rack/libinjection.rb', line 68 def notifier @notifier end |
#notifier_errors ⇒ Object (readonly)
Returns the value of attribute notifier_errors
68 69 70 |
# File 'lib/rack/libinjection.rb', line 68 def notifier_errors @notifier_errors end |
#notify_skipped ⇒ Object (readonly)
Returns the value of attribute notify_skipped
68 69 70 |
# File 'lib/rack/libinjection.rb', line 68 def notify_skipped @notify_skipped end |
#parser_errors ⇒ Object (readonly)
Returns the value of attribute parser_errors
68 69 70 |
# File 'lib/rack/libinjection.rb', line 68 def parser_errors @parser_errors end |
#path_decode_depth ⇒ Object (readonly)
Returns the value of attribute path_decode_depth
68 69 70 |
# File 'lib/rack/libinjection.rb', line 68 def path_decode_depth @path_decode_depth end |
#scan ⇒ Object (readonly)
Returns the value of attribute scan
68 69 70 |
# File 'lib/rack/libinjection.rb', line 68 def scan @scan end |
#scan_cookie_names ⇒ Object (readonly)
Returns the value of attribute scan_cookie_names
68 69 70 |
# File 'lib/rack/libinjection.rb', line 68 def @scan_cookie_names end |
#scan_sqli ⇒ Object (readonly)
Returns the value of attribute scan_sqli
68 69 70 |
# File 'lib/rack/libinjection.rb', line 68 def scan_sqli @scan_sqli end |
#scan_xss ⇒ Object (readonly)
Returns the value of attribute scan_xss
68 69 70 |
# File 'lib/rack/libinjection.rb', line 68 def scan_xss @scan_xss end |
#skipped_inputs ⇒ Object (readonly)
Returns the value of attribute skipped_inputs
68 69 70 |
# File 'lib/rack/libinjection.rb', line 68 def skipped_inputs @skipped_inputs end |
#threats ⇒ Object (readonly)
Returns the value of attribute threats
68 69 70 |
# File 'lib/rack/libinjection.rb', line 68 def threats @threats end |
Class Method Details
.bounded_non_negative_integer!(value, name, max) ⇒ Object
188 189 190 191 192 193 |
# File 'lib/rack/libinjection.rb', line 188 def self.bounded_non_negative_integer!(value, name, max) integer = non_negative_integer!(value, name) return integer if integer <= max raise ArgumentError, "#{name} must be <= #{max}" end |
.build(mode: :report, scan: DEFAULT_SCAN, threats: DEFAULT_THREATS, ignore_params: DEFAULT_IGNORE_PARAMS, ignore_headers: DEFAULT_IGNORE_HEADERS, scan_cookie_names: false, max_value_bytes: DEFAULT_MAX_VALUE_BYTES, max_depth: DEFAULT_MAX_DEPTH, path_decode_depth: DEFAULT_PATH_DECODE_DEPTH, parser_errors: :auto, notifier: nil, logger: nil, notifier_errors: :ignore, notify_skipped: true, skipped_inputs: :auto) ⇒ Object
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/rack/libinjection.rb', line 89 def self.build( mode: :report, scan: DEFAULT_SCAN, threats: DEFAULT_THREATS, ignore_params: DEFAULT_IGNORE_PARAMS, ignore_headers: DEFAULT_IGNORE_HEADERS, scan_cookie_names: false, max_value_bytes: DEFAULT_MAX_VALUE_BYTES, max_depth: DEFAULT_MAX_DEPTH, path_decode_depth: DEFAULT_PATH_DECODE_DEPTH, parser_errors: :auto, notifier: nil, logger: nil, notifier_errors: :ignore, notify_skipped: true, skipped_inputs: :auto ) raise ArgumentError, "pass either notifier: or logger:, not both" if notifier && logger mode = validate_mode(mode) scan = validate_scan(scan) threats = validate_threats(threats) ignored = normalize_param_names(ignore_params) ignored_headers = normalize_header_names(ignore_headers) new( mode: mode, scan: scan, threats: threats, scan_sqli: threats.include?(:sqli), scan_xss: threats.include?(:xss), detect_mask: detect_mask_for(threats), ignore_params: ignored, ignore_params_lookup: lookup_for(ignored), ignore_headers: ignored_headers, ignore_headers_lookup: lookup_for(ignored_headers), scan_cookie_names: !!, max_value_bytes: positive_integer!(max_value_bytes, :max_value_bytes), path_decode_depth: bounded_non_negative_integer!(path_decode_depth, :path_decode_depth, MAX_PATH_DECODE_DEPTH), max_depth: non_negative_integer!(max_depth, :max_depth), parser_errors: validate_parser_errors(parser_errors), notifier: notifier || build_notifier(logger), notifier_errors: validate_notifier_errors(notifier_errors), notify_skipped: !!notify_skipped, skipped_inputs: validate_skipped_inputs(skipped_inputs) ) end |
.build_notifier(logger) ⇒ Object
244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
# File 'lib/rack/libinjection.rb', line 244 def self.build_notifier(logger) if logger ->(event, payload) { logger.warn( "[rack-libinjection] #{event} type=#{payload[:type]} " \ "path=#{payload[:path]} #{payload[:location]}=#{payload[:key]}" ) } elsif defined?(::ActiveSupport::Notifications) ->(event, payload) { ::ActiveSupport::Notifications.instrument(event, payload) } else NOOP_NOTIFIER end end |
.detect_mask_for(threats) ⇒ Object
219 220 221 |
# File 'lib/rack/libinjection.rb', line 219 def self.detect_mask_for(threats) (threats.include?(:sqli) ? 1 : 0) | (threats.include?(:xss) ? 2 : 0) end |
.lookup_for(values) ⇒ Object
170 171 172 |
# File 'lib/rack/libinjection.rb', line 170 def self.lookup_for(values) values.each_with_object({}) { |key, index| index[key] = true }.freeze end |
.non_negative_integer!(value, name) ⇒ Object
181 182 183 184 185 186 |
# File 'lib/rack/libinjection.rb', line 181 def self.non_negative_integer!(value, name) integer = Integer(value) return integer if integer >= 0 raise ArgumentError, "#{name} must be >= 0" end |
.normalize_header_names(values) ⇒ Object
166 167 168 |
# File 'lib/rack/libinjection.rb', line 166 def self.normalize_header_names(values) Array(values).compact.map { |value| value.to_s.downcase }.uniq.freeze end |
.normalize_param_names(values) ⇒ Object
162 163 164 |
# File 'lib/rack/libinjection.rb', line 162 def self.normalize_param_names(values) Array(values).compact.map { |value| value.to_s.downcase }.uniq.freeze end |
.positive_integer!(value, name) ⇒ Object
174 175 176 177 178 179 |
# File 'lib/rack/libinjection.rb', line 174 def self.positive_integer!(value, name) integer = Integer(value) return integer if integer.positive? raise ArgumentError, "#{name} must be positive" end |
.validate_mode(value) ⇒ Object
195 196 197 198 199 200 |
# File 'lib/rack/libinjection.rb', line 195 def self.validate_mode(value) mode = value.to_sym return mode if VALID_MODES.include?(mode) raise ArgumentError, "mode must be one of: #{VALID_MODES.join(", ")}" end |
.validate_notifier_errors(value) ⇒ Object
230 231 232 233 234 235 |
# File 'lib/rack/libinjection.rb', line 230 def self.validate_notifier_errors(value) mode = value.to_sym return mode if VALID_NOTIFIER_ERRORS.include?(mode) raise ArgumentError, "notifier_errors must be one of: #{VALID_NOTIFIER_ERRORS.join(", ")}" end |
.validate_parser_errors(value) ⇒ Object
223 224 225 226 227 228 |
# File 'lib/rack/libinjection.rb', line 223 def self.validate_parser_errors(value) mode = value.to_sym return mode if VALID_PARSER_ERRORS.include?(mode) raise ArgumentError, "parser_errors must be one of: #{VALID_PARSER_ERRORS.join(", ")}" end |
.validate_scan(value) ⇒ Object
202 203 204 205 206 207 208 |
# File 'lib/rack/libinjection.rb', line 202 def self.validate_scan(value) scan = Array(value).map(&:to_sym).uniq.freeze unknown = scan - VALID_SCAN return scan if unknown.empty? raise ArgumentError, "scan contains unknown locations: #{unknown.join(", ")}" end |
.validate_skipped_inputs(value) ⇒ Object
237 238 239 240 241 242 |
# File 'lib/rack/libinjection.rb', line 237 def self.validate_skipped_inputs(value) mode = value.to_sym return mode if VALID_SKIPPED_INPUTS.include?(mode) raise ArgumentError, "skipped_inputs must be one of: #{VALID_SKIPPED_INPUTS.join(", ")}" end |
.validate_threats(value) ⇒ Object
210 211 212 213 214 215 216 217 |
# File 'lib/rack/libinjection.rb', line 210 def self.validate_threats(value) threats = Array(value).map(&:to_sym).uniq.freeze unknown = threats - VALID_THREATS raise ArgumentError, "threats must include at least one of: #{VALID_THREATS.join(", ")}" if threats.empty? return threats if unknown.empty? raise ArgumentError, "threats contains unknown types: #{unknown.join(", ")}" end |
Instance Method Details
#env_only_scan? ⇒ Boolean
145 |
# File 'lib/rack/libinjection.rb', line 145 def env_only_scan? = !scan_params? && ! |
#ignore_header?(normalized_key) ⇒ Boolean
160 |
# File 'lib/rack/libinjection.rb', line 160 def ignore_header?(normalized_key) = ignore_headers_lookup.key?(normalized_key) |
#ignore_param?(key) ⇒ Boolean
159 |
# File 'lib/rack/libinjection.rb', line 159 def ignore_param?(key) = ignore_params_lookup.key?(key.to_s.downcase) |
#notifier_active? ⇒ Boolean
143 |
# File 'lib/rack/libinjection.rb', line 143 def notifier_active? = !notifier.equal?(NOOP_NOTIFIER) |
#parser_error_policy ⇒ Object
147 148 149 150 151 |
# File 'lib/rack/libinjection.rb', line 147 def parser_error_policy return mode == :block ? :block : :report if parser_errors == :auto parser_errors end |
#scan_both_threats? ⇒ Boolean
142 |
# File 'lib/rack/libinjection.rb', line 142 def scan_both_threats? = scan_sqli && scan_xss |
#scan_cookies? ⇒ Boolean
141 |
# File 'lib/rack/libinjection.rb', line 141 def = scan.include?(:cookies) |
#scan_headers? ⇒ Boolean
140 |
# File 'lib/rack/libinjection.rb', line 140 def scan_headers? = scan.include?(:headers) |
#scan_params? ⇒ Boolean
138 |
# File 'lib/rack/libinjection.rb', line 138 def scan_params? = scan.include?(:params) |
#scan_path? ⇒ Boolean
139 |
# File 'lib/rack/libinjection.rb', line 139 def scan_path? = scan.include?(:path) |
#scan_query? ⇒ Boolean
137 |
# File 'lib/rack/libinjection.rb', line 137 def scan_query? = scan.include?(:query) |
#skipped_input_policy ⇒ Object
153 154 155 156 157 |
# File 'lib/rack/libinjection.rb', line 153 def skipped_input_policy return mode == :block ? :block : :report if skipped_inputs == :auto skipped_inputs end |