brakeman 0.9.2 → 1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/bin/brakeman +20 -5
  2. data/lib/brakeman.rb +54 -14
  3. data/lib/brakeman/call_index.rb +204 -0
  4. data/lib/{checks.rb → brakeman/checks.rb} +27 -12
  5. data/lib/{checks → brakeman/checks}/base_check.rb +36 -15
  6. data/lib/{checks → brakeman/checks}/check_basic_auth.rb +3 -3
  7. data/lib/{checks → brakeman/checks}/check_cross_site_scripting.rb +22 -19
  8. data/lib/{checks → brakeman/checks}/check_default_routes.rb +7 -5
  9. data/lib/{checks → brakeman/checks}/check_escape_function.rb +3 -4
  10. data/lib/{checks → brakeman/checks}/check_evaluation.rb +8 -6
  11. data/lib/{checks → brakeman/checks}/check_execute.rb +14 -14
  12. data/lib/brakeman/checks/check_file_access.rb +52 -0
  13. data/lib/{checks → brakeman/checks}/check_filter_skipping.rb +3 -4
  14. data/lib/{checks → brakeman/checks}/check_forgery_setting.rb +3 -3
  15. data/lib/{checks → brakeman/checks}/check_mail_to.rb +7 -6
  16. data/lib/{checks → brakeman/checks}/check_mass_assignment.rb +27 -7
  17. data/lib/{checks → brakeman/checks}/check_model_attributes.rb +7 -7
  18. data/lib/{checks → brakeman/checks}/check_nested_attributes.rb +3 -4
  19. data/lib/{checks → brakeman/checks}/check_quote_table_name.rb +6 -5
  20. data/lib/{checks → brakeman/checks}/check_redirect.rb +31 -15
  21. data/lib/{checks → brakeman/checks}/check_render.rb +5 -3
  22. data/lib/{checks → brakeman/checks}/check_response_splitting.rb +3 -4
  23. data/lib/brakeman/checks/check_send_file.rb +17 -0
  24. data/lib/{checks → brakeman/checks}/check_session_settings.rb +16 -12
  25. data/lib/{checks → brakeman/checks}/check_sql.rb +29 -17
  26. data/lib/{checks → brakeman/checks}/check_strip_tags.rb +6 -5
  27. data/lib/{checks → brakeman/checks}/check_translate_bug.rb +7 -6
  28. data/lib/{checks → brakeman/checks}/check_validation_regex.rb +3 -3
  29. data/lib/{checks → brakeman/checks}/check_without_protection.rb +8 -8
  30. data/lib/brakeman/processor.rb +93 -0
  31. data/lib/{processors → brakeman/processors}/alias_processor.rb +9 -7
  32. data/lib/{processors → brakeman/processors}/base_processor.rb +5 -5
  33. data/lib/brakeman/processors/config_processor.rb +14 -0
  34. data/lib/{processors → brakeman/processors}/controller_alias_processor.rb +8 -8
  35. data/lib/{processors → brakeman/processors}/controller_processor.rb +6 -6
  36. data/lib/{processors → brakeman/processors}/erb_template_processor.rb +2 -2
  37. data/lib/{processors → brakeman/processors}/erubis_template_processor.rb +2 -3
  38. data/lib/{processors → brakeman/processors}/gem_processor.rb +3 -2
  39. data/lib/{processors → brakeman/processors}/haml_template_processor.rb +3 -3
  40. data/lib/brakeman/processors/lib/find_all_calls.rb +105 -0
  41. data/lib/{processors → brakeman/processors}/lib/find_call.rb +4 -4
  42. data/lib/{processors → brakeman/processors}/lib/processor_helper.rb +1 -1
  43. data/lib/{processors → brakeman/processors}/lib/rails2_config_processor.rb +10 -13
  44. data/lib/{processors → brakeman/processors}/lib/rails2_route_processor.rb +6 -5
  45. data/lib/{processors → brakeman/processors}/lib/rails3_config_processor.rb +7 -10
  46. data/lib/{processors → brakeman/processors}/lib/rails3_route_processor.rb +13 -5
  47. data/lib/{processors → brakeman/processors}/lib/render_helper.rb +12 -4
  48. data/lib/{processors → brakeman/processors}/lib/route_helper.rb +1 -1
  49. data/lib/{processors → brakeman/processors}/library_processor.rb +4 -4
  50. data/lib/{processors → brakeman/processors}/model_processor.rb +3 -3
  51. data/lib/{processors → brakeman/processors}/output_processor.rb +5 -6
  52. data/lib/{processors → brakeman/processors}/params_processor.rb +1 -2
  53. data/lib/brakeman/processors/route_processor.rb +17 -0
  54. data/lib/{processors → brakeman/processors}/template_alias_processor.rb +5 -5
  55. data/lib/{processors → brakeman/processors}/template_processor.rb +2 -2
  56. data/lib/{report.rb → brakeman/report.rb} +54 -48
  57. data/lib/{scanner.rb → brakeman/scanner.rb} +26 -17
  58. data/lib/{tracker.rb → brakeman/tracker.rb} +47 -38
  59. data/lib/{util.rb → brakeman/util.rb} +16 -1
  60. data/lib/brakeman/version.rb +3 -0
  61. data/lib/{warning.rb → brakeman/warning.rb} +9 -9
  62. metadata +81 -69
  63. data/lib/checks/check_file_access.rb +0 -48
  64. data/lib/checks/check_send_file.rb +0 -15
  65. data/lib/format/style.css +0 -105
  66. data/lib/processor.rb +0 -91
  67. data/lib/processors/config_processor.rb +0 -5
  68. data/lib/processors/lib/find_model_call.rb +0 -43
  69. data/lib/processors/route_processor.rb +0 -11
  70. data/lib/version.rb +0 -1
@@ -1,4 +1,4 @@
1
- require 'processors/base_processor'
1
+ require 'brakeman/processors/base_processor'
2
2
 
3
3
  #Finds method calls matching the given target(s).
4
4
  #
@@ -29,10 +29,10 @@ require 'processors/base_processor'
29
29
  #
30
30
  # #Find all calls to sub, sub!, gsub, or gsub!
31
31
  # FindCall.new nil, /^g?sub!?$/
32
- class FindCall < BaseProcessor
32
+ class Brakeman::FindCall < Brakeman::BaseProcessor
33
33
 
34
- def initialize targets, methods, in_depth = false
35
- super(nil)
34
+ def initialize targets, methods, tracker, in_depth = false
35
+ super tracker
36
36
  @calls = []
37
37
  @find_targets = targets
38
38
  @find_methods = methods
@@ -1,5 +1,5 @@
1
1
  #Contains a couple shared methods for Processors.
2
- module ProcessorHelper
2
+ module Brakeman::ProcessorHelper
3
3
 
4
4
  #Sets the current module.
5
5
  def process_module exp
@@ -1,12 +1,9 @@
1
- require 'processors/base_processor'
2
- require 'processors/alias_processor'
3
-
4
1
  #Replace block variable in
5
2
  #
6
3
  # Rails::Initializer.run |config|
7
4
  #
8
5
  #with this value so we can keep track of it.
9
- RAILS_CONFIG = Sexp.new(:const, :"!BRAKEMAN_RAILS_CONFIG")
6
+ Brakeman::RAILS_CONFIG = Sexp.new(:const, :"!BRAKEMAN_RAILS_CONFIG") unless defined? Brakeman::RAILS_CONFIG
10
7
 
11
8
  #Processes configuration. Results are put in tracker.config.
12
9
  #
@@ -22,7 +19,7 @@ RAILS_CONFIG = Sexp.new(:const, :"!BRAKEMAN_RAILS_CONFIG")
22
19
  # tracker.config[:rails][:action_controller][:session_store]
23
20
  #
24
21
  #Values for tracker.config[:rails] will still be Sexps.
25
- class ConfigProcessor < BaseProcessor
22
+ class Brakeman::Rails2ConfigProcessor < Brakeman::BaseProcessor
26
23
  def initialize *args
27
24
  super
28
25
  @tracker.config[:rails] ||= {}
@@ -30,7 +27,7 @@ class ConfigProcessor < BaseProcessor
30
27
 
31
28
  #Use this method to process configuration file
32
29
  def process_config src
33
- res = ConfigAliasProcessor.new.process_safely(src)
30
+ res = Brakeman::ConfigAliasProcessor.new.process_safely(src)
34
31
  process res
35
32
  end
36
33
 
@@ -49,7 +46,7 @@ class ConfigProcessor < BaseProcessor
49
46
 
50
47
  #Look for configuration settings
51
48
  def process_attrasgn exp
52
- if exp[1] == RAILS_CONFIG
49
+ if exp[1] == Brakeman::RAILS_CONFIG
53
50
  #Get rid of '=' at end
54
51
  attribute = exp[2].to_s[0..-2].to_sym
55
52
  if exp[3].length > 2
@@ -86,12 +83,12 @@ class ConfigProcessor < BaseProcessor
86
83
  def include_rails_config? exp
87
84
  target = exp[1]
88
85
  if call? target
89
- if target[1] == RAILS_CONFIG
86
+ if target[1] == Brakeman::RAILS_CONFIG
90
87
  true
91
88
  else
92
89
  include_rails_config? target
93
90
  end
94
- elsif target == RAILS_CONFIG
91
+ elsif target == Brakeman::RAILS_CONFIG
95
92
  true
96
93
  else
97
94
  false
@@ -110,7 +107,7 @@ class ConfigProcessor < BaseProcessor
110
107
  attribute = exp[2].to_s[0..-2].to_sym
111
108
  get_rails_config(exp[1]) << attribute
112
109
  elsif call? exp
113
- if exp[1] == RAILS_CONFIG
110
+ if exp[1] == Brakeman::RAILS_CONFIG
114
111
  [exp[2]]
115
112
  else
116
113
  get_rails_config(exp[1]) << exp[2]
@@ -122,7 +119,7 @@ class ConfigProcessor < BaseProcessor
122
119
  end
123
120
 
124
121
  #This is necessary to replace block variable so we can track config settings
125
- class ConfigAliasProcessor < AliasProcessor
122
+ class Brakeman::ConfigAliasProcessor < Brakeman::AliasProcessor
126
123
 
127
124
  RAILS_INIT = Sexp.new(:colon2, Sexp.new(:const, :Rails), :Initializer)
128
125
 
@@ -132,13 +129,13 @@ class ConfigAliasProcessor < AliasProcessor
132
129
  # ...
133
130
  # end
134
131
  #
135
- #and replace config with RAILS_CONFIG
132
+ #and replace config with Brakeman::RAILS_CONFIG
136
133
  def process_iter exp
137
134
  target = exp[1][1]
138
135
  method = exp[1][2]
139
136
 
140
137
  if sexp? target and target == RAILS_INIT and method == :run
141
- exp[2][2] = RAILS_CONFIG
138
+ exp[2][2] = Brakeman::RAILS_CONFIG
142
139
  end
143
140
 
144
141
  process_default exp
@@ -1,10 +1,11 @@
1
- require 'processors/base_processor'
1
+ require 'brakeman/processors/base_processor'
2
+
2
3
  #Processes the Sexp from routes.rb. Stores results in tracker.routes.
3
4
  #
4
5
  #Note that it is only interested in determining what methods on which
5
6
  #controllers are used as routes, not the generated URLs for routes.
6
- class RoutesProcessor < BaseProcessor
7
- include RouteHelper
7
+ class Brakeman::Rails2RoutesProcessor < Brakeman::BaseProcessor
8
+ include Brakeman::RouteHelper
8
9
 
9
10
  attr_reader :map, :nested, :current_controller
10
11
 
@@ -22,7 +23,7 @@ class RoutesProcessor < BaseProcessor
22
23
  #This method first calls RouteAliasProcessor#process_safely on the +exp+,
23
24
  #so it does not modify the +exp+.
24
25
  def process_routes exp
25
- process RouteAliasProcessor.new.process_safely(exp)
26
+ process Brakeman::RouteAliasProcessor.new.process_safely(exp)
26
27
  end
27
28
 
28
29
  #Looking for mapping of routes
@@ -273,7 +274,7 @@ end
273
274
 
274
275
  #This is for a really specific case where a hash is used as arguments
275
276
  #to one of the map methods.
276
- class RouteAliasProcessor < AliasProcessor
277
+ class Brakeman::RouteAliasProcessor < Brakeman::AliasProcessor
277
278
 
278
279
  #This replaces
279
280
  # { :some => :hash }.keys
@@ -1,7 +1,4 @@
1
- require 'processors/base_processor'
2
- require 'processors/alias_processor'
3
-
4
- RAILS_CONFIG = Sexp.new(:call, nil, :config, Sexp.new(:arglist))
1
+ Brakeman::RAILS_CONFIG = Sexp.new(:call, nil, :config, Sexp.new(:arglist))
5
2
 
6
3
  #Processes configuration. Results are put in tracker.config.
7
4
  #
@@ -17,7 +14,7 @@ RAILS_CONFIG = Sexp.new(:call, nil, :config, Sexp.new(:arglist))
17
14
  # tracker.config[:rails][:active_record][:whitelist_attributes]
18
15
  #
19
16
  #Values for tracker.config[:rails] will still be Sexps.
20
- class ConfigProcessor < BaseProcessor
17
+ class Brakeman::Rails3ConfigProcessor < Brakeman::BaseProcessor
21
18
  def initialize *args
22
19
  super
23
20
  @tracker.config[:rails] ||= {}
@@ -26,7 +23,7 @@ class ConfigProcessor < BaseProcessor
26
23
 
27
24
  #Use this method to process configuration file
28
25
  def process_config src
29
- res = AliasProcessor.new.process_safely(src)
26
+ res = Brakeman::AliasProcessor.new.process_safely(src)
30
27
  process res
31
28
  end
32
29
 
@@ -56,7 +53,7 @@ class ConfigProcessor < BaseProcessor
56
53
  def process_attrasgn exp
57
54
  return exp unless @inside_config
58
55
 
59
- if exp[1] == RAILS_CONFIG
56
+ if exp[1] == Brakeman::RAILS_CONFIG
60
57
  #Get rid of '=' at end
61
58
  attribute = exp[2].to_s[0..-2].to_sym
62
59
  if exp[3].length > 2
@@ -83,12 +80,12 @@ class ConfigProcessor < BaseProcessor
83
80
  def include_rails_config? exp
84
81
  target = exp[1]
85
82
  if call? target
86
- if target[1] == RAILS_CONFIG
83
+ if target[1] == Brakeman::RAILS_CONFIG
87
84
  true
88
85
  else
89
86
  include_rails_config? target
90
87
  end
91
- elsif target == RAILS_CONFIG
88
+ elsif target == Brakeman::RAILS_CONFIG
92
89
  true
93
90
  else
94
91
  false
@@ -107,7 +104,7 @@ class ConfigProcessor < BaseProcessor
107
104
  attribute = exp[2].to_s[0..-2].to_sym
108
105
  get_rails_config(exp[1]) << attribute
109
106
  elsif call? exp
110
- if exp[1] == RAILS_CONFIG
107
+ if exp[1] == Brakeman::RAILS_CONFIG
111
108
  [exp[2]]
112
109
  else
113
110
  get_rails_config(exp[1]) << exp[2]
@@ -2,8 +2,8 @@
2
2
  #
3
3
  #Note that it is only interested in determining what methods on which
4
4
  #controllers are used as routes, not the generated URLs for routes.
5
- class RoutesProcessor < BaseProcessor
6
- include RouteHelper
5
+ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
6
+ include Brakeman::RouteHelper
7
7
 
8
8
  attr_reader :map, :nested, :current_controller
9
9
 
@@ -126,7 +126,7 @@ class RoutesProcessor < BaseProcessor
126
126
  def process_verb exp
127
127
  args = exp[3][1..-1]
128
128
 
129
- if symbol? args[0]
129
+ if symbol? args[0] and not hash? args[1]
130
130
  @tracker.routes[@current_controller] << args[0][1]
131
131
  elsif hash? args[1]
132
132
  hash_iterate args[1] do |k, v|
@@ -162,7 +162,9 @@ class RoutesProcessor < BaseProcessor
162
162
 
163
163
  def process_resources exp
164
164
  if exp[3] and exp[3][2] and exp[3][2][0] == :hash
165
+ self.current_controller = exp[3][1][1]
165
166
  #handle hash
167
+ add_resources_routes
166
168
  elsif exp[3][1..-1].all? { |s| symbol? s }
167
169
  exp[3][1..-1].each do |s|
168
170
  self.current_controller = s[1]
@@ -174,9 +176,15 @@ class RoutesProcessor < BaseProcessor
174
176
  end
175
177
 
176
178
  def process_resource exp
179
+ #Does resource even take more than one controller name?
177
180
  exp[3][1..-1].each do |s|
178
- self.current_controller = s[1]
179
- add_resource_routes
181
+ if symbol? s
182
+ self.current_controller = pluralize(s[1].to_s)
183
+ add_resource_routes
184
+ else
185
+ #handle something else, like options
186
+ #or something?
187
+ end
180
188
  end
181
189
 
182
190
  exp
@@ -1,7 +1,7 @@
1
1
  require 'digest/sha1'
2
2
 
3
3
  #Processes a call to render() in a controller or template
4
- module RenderHelper
4
+ module Brakeman::RenderHelper
5
5
 
6
6
  #Process s(:render, TYPE, OPTIONS)
7
7
  def process_render exp
@@ -50,7 +50,7 @@ module RenderHelper
50
50
  name = name.to_s.gsub(/^\//, "")
51
51
  template = @tracker.templates[name.to_sym]
52
52
  unless template
53
- warn "[Notice] No such template: #{name}" if OPTIONS[:debug]
53
+ warn "[Notice] No such template: #{name}" if @tracker.options[:debug]
54
54
  return
55
55
  end
56
56
 
@@ -99,13 +99,21 @@ module RenderHelper
99
99
  end
100
100
  end
101
101
 
102
- template_env[Sexp.new(:call, nil, variable, Sexp.new(:arglist))] = Sexp.new(:call, Sexp.new(:const, Tracker::UNKNOWN_MODEL), :new, Sexp.new(:arglist))
102
+ template_env[Sexp.new(:call, nil, variable, Sexp.new(:arglist))] = Sexp.new(:call, Sexp.new(:const, Brakeman::Tracker::UNKNOWN_MODEL), :new, Sexp.new(:arglist))
103
+ end
104
+
105
+ #Set original_line for values so it is clear
106
+ #that values came from another file
107
+ template_env.all.each do |var, value|
108
+ unless value.original_line
109
+ value.original_line = value.line
110
+ end
103
111
  end
104
112
 
105
113
  #Run source through AliasProcessor with instance variables from the
106
114
  #current environment.
107
115
  #TODO: Add in :locals => { ... } to environment
108
- src = TemplateAliasProcessor.new(@tracker, template).process_safely(template[:src], template_env)
116
+ src = Brakeman::TemplateAliasProcessor.new(@tracker, template).process_safely(template[:src], template_env)
109
117
 
110
118
  #Run alias-processed src through the template processor to pull out
111
119
  #information and outputs.
@@ -1,4 +1,4 @@
1
- module RouteHelper
1
+ module Brakeman::RouteHelper
2
2
  #Manage Controller prefixes
3
3
  #@prefix is an Array, but this method returns a string
4
4
  #suitable for prefixing onto a controller name.
@@ -1,13 +1,13 @@
1
- require 'processors/base_processor'
2
- require 'processors/alias_processor'
1
+ require 'brakeman/processors/base_processor'
2
+ require 'brakeman/processors/alias_processor'
3
3
 
4
4
  #Process generic library and stores it in Tracker.libs
5
- class LibraryProcessor < BaseProcessor
5
+ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
6
6
 
7
7
  def initialize tracker
8
8
  super
9
9
  @file_name = nil
10
- @alias_processor = AliasProcessor.new
10
+ @alias_processor = Brakeman::AliasProcessor.new
11
11
  end
12
12
 
13
13
  def process_library src, file_name = nil
@@ -1,7 +1,7 @@
1
- require 'processors/base_processor'
1
+ require 'brakeman/processors/base_processor'
2
2
 
3
3
  #Processes models. Puts results in tracker.models
4
- class ModelProcessor < BaseProcessor
4
+ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
5
5
  def initialize tracker
6
6
  super
7
7
  @model = nil
@@ -19,7 +19,7 @@ class ModelProcessor < BaseProcessor
19
19
  #s(:class, NAME, PARENT, s(:scope ...))
20
20
  def process_class exp
21
21
  if @model
22
- warn "[Notice] Skipping inner class: #{class_name exp[1]}" if OPTIONS[:debug]
22
+ warn "[Notice] Skipping inner class: #{class_name exp[1]}" if @tracker.options[:debug]
23
23
  ignore
24
24
  else
25
25
  @model = { :name => class_name(exp[1]),
@@ -1,13 +1,12 @@
1
- require 'rubygems'
2
1
  require 'ruby2ruby'
3
- require 'util'
2
+ require 'brakeman/util'
4
3
 
5
4
  #Produces formatted output strings from Sexps.
6
5
  #Recommended usage is
7
6
  #
8
7
  # OutputProcessor.new.format(Sexp.new(:str, "hello"))
9
- class OutputProcessor < Ruby2Ruby
10
- include Util
8
+ class Brakeman::OutputProcessor < Ruby2Ruby
9
+ include Brakeman::Util
11
10
 
12
11
  #Copies +exp+ and then formats it.
13
12
  def format exp
@@ -20,7 +19,7 @@ class OutputProcessor < Ruby2Ruby
20
19
  begin
21
20
  super exp if sexp? exp and not exp.empty?
22
21
  rescue Exception => e
23
- warn "While formatting #{exp}: #{e}\n#{e.backtrace.join("\n")}" if OPTIONS[:debug]
22
+ warn "While formatting #{exp}: #{e}\n#{e.backtrace.join("\n")}" if @tracker.options[:debug]
24
23
  end
25
24
  end
26
25
 
@@ -203,7 +202,7 @@ class OutputProcessor < Ruby2Ruby
203
202
  end
204
203
 
205
204
  def process_const exp
206
- if exp[0] == Tracker::UNKNOWN_MODEL
205
+ if exp[0] == Brakeman::Tracker::UNKNOWN_MODEL
207
206
  exp.clear
208
207
  "(Unresolved Model)"
209
208
  else
@@ -1,9 +1,8 @@
1
- require 'rubygems'
2
1
  require 'sexp_processor'
3
2
  require 'set'
4
3
 
5
4
  #Looks for request parameters. Not used currently.
6
- class ParamsProcessor < SexpProcessor
5
+ class Brakeman::ParamsProcessor < SexpProcessor
7
6
  attr_reader :result
8
7
 
9
8
  def initialize
@@ -0,0 +1,17 @@
1
+ require 'brakeman/processors/base_processor'
2
+ require 'brakeman/processors/alias_processor'
3
+ require 'brakeman/processors/lib/route_helper'
4
+ require 'brakeman/util'
5
+ require 'brakeman/processors/lib/rails3_route_processor.rb'
6
+ require 'brakeman/processors/lib/rails2_route_processor.rb'
7
+ require 'set'
8
+
9
+ class Brakeman::RoutesProcessor
10
+ def self.new tracker
11
+ if tracker.options[:rails3]
12
+ Brakeman::Rails3RoutesProcessor.new tracker
13
+ else
14
+ Brakeman::Rails2RoutesProcessor.new tracker
15
+ end
16
+ end
17
+ end
@@ -1,11 +1,11 @@
1
1
  require 'set'
2
- require 'processors/alias_processor'
3
- require 'processors/lib/render_helper'
2
+ require 'brakeman/processors/alias_processor'
3
+ require 'brakeman/processors/lib/render_helper'
4
4
 
5
5
  #Processes aliasing in templates.
6
6
  #Handles calls to +render+.
7
- class TemplateAliasProcessor < AliasProcessor
8
- include RenderHelper
7
+ class Brakeman::TemplateAliasProcessor < Brakeman::AliasProcessor
8
+ include Brakeman::RenderHelper
9
9
 
10
10
  FORM_METHODS = Set.new([:form_for, :remote_form_for, :form_remote_for])
11
11
 
@@ -44,7 +44,7 @@ class TemplateAliasProcessor < AliasProcessor
44
44
  if model == target[1]
45
45
  env[Sexp.new(:lvar, args[1])] = Sexp.new(:call, model, :new, Sexp.new(:arglist))
46
46
  else
47
- env[Sexp.new(:lvar, args[1])] = Sexp.new(:call, Sexp.new(:const, Tracker::UNKNOWN_MODEL), :new, Sexp.new(:arglist))
47
+ env[Sexp.new(:lvar, args[1])] = Sexp.new(:call, Sexp.new(:const, Brakeman::Tracker::UNKNOWN_MODEL), :new, Sexp.new(:arglist))
48
48
  end
49
49
 
50
50
  process block if sexp? block
@@ -1,7 +1,7 @@
1
- require 'processors/base_processor'
1
+ require 'brakeman/processors/base_processor'
2
2
 
3
3
  #Base Processor for templates/views
4
- class TemplateProcessor < BaseProcessor
4
+ class Brakeman::TemplateProcessor < Brakeman::BaseProcessor
5
5
 
6
6
  #Initializes template information.
7
7
  def initialize tracker, template_name, called_from = nil, file_name = nil
@@ -1,9 +1,8 @@
1
- require 'rubygems'
2
1
  require 'cgi'
3
2
  require 'set'
4
3
  require 'ruport'
5
- require 'processors/output_processor'
6
- require 'util'
4
+ require 'brakeman/processors/output_processor'
5
+ require 'brakeman/util'
7
6
 
8
7
  #Fix for Ruport under 1.9
9
8
  #as reported here: https://github.com/ruport/ruport/pull/7
@@ -19,8 +18,8 @@ end
19
18
  #Generates a report based on the Tracker and the results of
20
19
  #Tracker#run_checks. Be sure to +run_checks+ before generating
21
20
  #a report.
22
- class Report
23
- include Util
21
+ class Brakeman::Report
22
+ include Brakeman::Util
24
23
 
25
24
  attr_reader :tracker, :checks
26
25
 
@@ -47,10 +46,10 @@ class Report
47
46
  #Add number of high confidence warnings in summary.
48
47
  #Skipping for CSV because it makes the cell text instead of
49
48
  #a number.
50
- unless OPTIONS[:output_format] == :to_csv
49
+ unless tracker.options[:output_format] == :to_csv
51
50
  summary = warnings_summary
52
51
 
53
- if OPTIONS[:output_format] == :to_html
52
+ if tracker.options[:output_format] == :to_html
54
53
  warnings = "#{warnings} <span class='high-confidence'>(#{summary[:high_confidence]})</span>"
55
54
  else
56
55
  warnings = "#{warnings} (#{summary[:high_confidence]})"
@@ -84,9 +83,9 @@ class Report
84
83
 
85
84
 
86
85
  tracker.errors.each do |w|
87
- p w if OPTIONS[:debug]
86
+ p w if tracker.options[:debug]
88
87
 
89
- if OPTIONS[:output_format] == :to_html
88
+ if tracker.options[:output_format] == :to_html
90
89
  w[:error] = CGI.escapeHTML w[:error]
91
90
  end
92
91
 
@@ -103,10 +102,10 @@ class Report
103
102
  def generate_warnings
104
103
  table = Ruport::Data::Table(["Confidence", "Class", "Method", "Warning Type", "Message"])
105
104
  checks.warnings.each do |warning|
106
- next if warning.confidence > OPTIONS[:min_confidence]
105
+ next if warning.confidence > tracker.options[:min_confidence]
107
106
  w = warning.to_row
108
107
 
109
- if OPTIONS[:output_format] == :to_html
108
+ if tracker.options[:output_format] == :to_html
110
109
  w["Confidence"] = HTML_CONFIDENCE[w["Confidence"]]
111
110
  w["Message"] = with_context warning, w["Message"]
112
111
  else
@@ -133,10 +132,10 @@ class Report
133
132
  unless checks.template_warnings.empty?
134
133
  table = Ruport::Data::Table(["Confidence", "Template", "Warning Type", "Message"])
135
134
  checks.template_warnings.each do |warning|
136
- next if warning.confidence > OPTIONS[:min_confidence]
135
+ next if warning.confidence > tracker.options[:min_confidence]
137
136
  w = warning.to_row :template
138
137
 
139
- if OPTIONS[:output_format] == :to_html
138
+ if tracker.options[:output_format] == :to_html
140
139
  w["Confidence"] = HTML_CONFIDENCE[w["Confidence"]]
141
140
  w["Message"] = with_context warning, w["Message"]
142
141
  else
@@ -164,10 +163,10 @@ class Report
164
163
  unless checks.model_warnings.empty?
165
164
  table = Ruport::Data::Table(["Confidence", "Model", "Warning Type", "Message"])
166
165
  checks.model_warnings.each do |warning|
167
- next if warning.confidence > OPTIONS[:min_confidence]
166
+ next if warning.confidence > tracker.options[:min_confidence]
168
167
  w = warning.to_row :model
169
168
 
170
- if OPTIONS[:output_format] == :to_html
169
+ if tracker.options[:output_format] == :to_html
171
170
  w["Confidence"] = HTML_CONFIDENCE[w["Confidence"]]
172
171
  w["Message"] = with_context warning, w["Message"]
173
172
  else
@@ -195,10 +194,10 @@ class Report
195
194
  unless checks.controller_warnings.empty?
196
195
  table = Ruport::Data::Table(["Confidence", "Controller", "Warning Type", "Message"])
197
196
  checks.controller_warnings.each do |warning|
198
- next if warning.confidence > OPTIONS[:min_confidence]
197
+ next if warning.confidence > tracker.options[:min_confidence]
199
198
  w = warning.to_row :controller
200
199
 
201
- if OPTIONS[:output_format] == :to_html
200
+ if tracker.options[:output_format] == :to_html
202
201
  w["Confidence"] = HTML_CONFIDENCE[w["Confidence"]]
203
202
  w["Message"] = with_context warning, w["Message"]
204
203
  else
@@ -259,13 +258,13 @@ class Report
259
258
 
260
259
  #Generate listings of templates and their output
261
260
  def generate_templates
262
- out_processor = OutputProcessor.new
261
+ out_processor = Brakeman::OutputProcessor.new
263
262
  table = Ruport::Data::Table(["Name", "Output"])
264
263
  tracker.templates.each do |name, template|
265
264
  unless template[:outputs].empty?
266
265
  template[:outputs].each do |out|
267
266
  out = out_processor.format out
268
- out = CGI.escapeHTML(out) if OPTIONS[:output_format] == :to_html
267
+ out = CGI.escapeHTML(out) if tracker.options[:output_format] == :to_html
269
268
  table << { "Name" => name,
270
269
  "Output" => out.gsub("\n", ";").gsub(/\s+/, " ") }
271
270
  end
@@ -281,12 +280,12 @@ class Report
281
280
  generate_overview.to_html << "<br/>" <<
282
281
  generate_warning_overview.to_html
283
282
 
284
- if OPTIONS[:report_routes] or OPTIONS[:debug]
283
+ if tracker.options[:report_routes] or tracker.options[:debug]
285
284
  out << "<h2>Controllers</h2>" <<
286
285
  generate_controllers.to_html
287
286
  end
288
287
 
289
- if OPTIONS[:debug]
288
+ if tracker.options[:debug]
290
289
  out << "<h2>Templates</h2>" <<
291
290
  generate_templates.to_html
292
291
  end
@@ -318,12 +317,12 @@ class Report
318
317
  generate_overview.to_s << "\n" <<
319
318
  generate_warning_overview.to_s << "\n"
320
319
 
321
- if OPTIONS[:report_routes] or OPTIONS[:debug]
320
+ if tracker.options[:report_routes] or tracker.options[:debug]
322
321
  out << "+CONTROLLERS+\n" <<
323
322
  generate_controllers.to_s << "\n"
324
323
  end
325
324
 
326
- if OPTIONS[:debug]
325
+ if tracker.options[:debug]
327
326
  out << "+TEMPLATES+\n\n" <<
328
327
  generate_templates.to_s << "\n"
329
328
  end
@@ -353,12 +352,12 @@ class Report
353
352
  generate_overview.to_csv << "\n" <<
354
353
  generate_warning_overview.to_csv << "\n"
355
354
 
356
- if OPTIONS[:report_routes] or OPTIONS[:debug]
355
+ if tracker.options[:report_routes] or tracker.options[:debug]
357
356
  out << "CONTROLLERS\n" <<
358
357
  generate_controllers.to_csv << "\n"
359
358
  end
360
359
 
361
- if OPTIONS[:debug]
360
+ if tracker.options[:debug]
362
361
  out << "TEMPLATES\n\n" <<
363
362
  generate_templates.to_csv << "\n"
364
363
  end
@@ -389,19 +388,19 @@ class Report
389
388
  def rails_version
390
389
  if version = tracker.config[:rails_version]
391
390
  return version
392
- elsif OPTIONS[:rails3]
391
+ elsif tracker.options[:rails3]
393
392
  return "3.x"
394
393
  else
395
394
  return "Unknown"
396
395
  end
397
396
  end
398
397
 
399
- #Return header for HTML output. Uses CSS from OPTIONS[:html_style]
398
+ #Return header for HTML output. Uses CSS from tracker.options[:html_style]
400
399
  def html_header
401
- if File.exist? OPTIONS[:html_style]
402
- css = File.read OPTIONS[:html_style]
400
+ if File.exist? tracker.options[:html_style]
401
+ css = File.read tracker.options[:html_style]
403
402
  else
404
- raise "Cannot find CSS stylesheet for HTML: #{OPTIONS[:html_style]}"
403
+ raise "Cannot find CSS stylesheet for HTML: #{tracker.options[:html_style]}"
405
404
  end
406
405
 
407
406
  <<-HTML
@@ -410,11 +409,15 @@ class Report
410
409
  <head>
411
410
  <title>Brakeman Report</title>
412
411
  <script type="text/javascript">
413
- function toggle(context){
414
- if (document.getElementById(context).style.display != "block")
415
- document.getElementById(context).style.display = "block";
412
+ function toggle(context) {
413
+ var elem = document.getElementById(context);
414
+
415
+ if (elem.style.display != "block")
416
+ elem.style.display = "block";
416
417
  else
417
- document.getElementById(context).style.display = "none";
418
+ elem.style.display = "none";
419
+
420
+ elem.parentNode.scrollIntoView();
418
421
  }
419
422
  </script>
420
423
  <style type="text/css">
@@ -431,7 +434,7 @@ class Report
431
434
  <th>Checks Performed</th>
432
435
  </tr>
433
436
  <tr>
434
- <td>#{File.expand_path OPTIONS[:app_path]}</td>
437
+ <td>#{File.expand_path tracker.options[:app_path]}</td>
435
438
  <td>#{rails_version}</td>
436
439
  <td>#{Time.now}</td>
437
440
  <td>#{checks.checks_run.sort.join(", ")}</td>
@@ -442,13 +445,13 @@ class Report
442
445
 
443
446
  #Generate header for text output
444
447
  def text_header
445
- "\n+BRAKEMAN REPORT+\n\nApplication path: #{File.expand_path OPTIONS[:app_path]}\nRails version: #{rails_version}\nGenerated at #{Time.now}\nChecks run: #{checks.checks_run.sort.join(", ")}\n"
448
+ "\n+BRAKEMAN REPORT+\n\nApplication path: #{File.expand_path tracker.options[:app_path]}\nRails version: #{rails_version}\nGenerated at #{Time.now}\nChecks run: #{checks.checks_run.sort.join(", ")}\n"
446
449
  end
447
450
 
448
451
  #Generate header for CSV output
449
452
  def csv_header
450
453
  header = Ruport::Data::Table(["Application Path", "Report Generation Time", "Checks Performed", "Rails Version"])
451
- header << [File.expand_path(OPTIONS[:app_path]), Time.now.to_s, checks.checks_run.sort.join(", "), rails_version]
454
+ header << [File.expand_path(tracker.options[:app_path]), Time.now.to_s, checks.checks_run.sort.join(", "), rails_version]
452
455
  "BRAKEMAN REPORT\n\n" << header.to_csv
453
456
  end
454
457
 
@@ -465,10 +468,13 @@ class Report
465
468
  checks.template_warnings].each do |warnings|
466
469
 
467
470
  warnings.each do |warning|
468
- summary[warning.warning_type.to_s] += 1
471
+ unless warning.confidence > tracker.options[:min_confidence]
472
+
473
+ summary[warning.warning_type.to_s] += 1
469
474
 
470
- if warning.confidence == 0
471
- high_confidence_warnings += 1
475
+ if warning.confidence == 0
476
+ high_confidence_warnings += 1
477
+ end
472
478
  end
473
479
  end
474
480
  end
@@ -480,7 +486,7 @@ class Report
480
486
  #Return file name related to given warning. Uses +warning.file+ if it exists
481
487
  def file_for warning
482
488
  if warning.file
483
- File.expand_path warning.file, OPTIONS[:app_path]
489
+ File.expand_path warning.file, tracker.options[:app_path]
484
490
  else
485
491
  case warning.warning_set
486
492
  when :controller
@@ -518,7 +524,7 @@ class Report
518
524
  end
519
525
  end
520
526
 
521
- path = OPTIONS[:app_path]
527
+ path = tracker.options[:app_path]
522
528
 
523
529
  case type
524
530
  when :controller
@@ -584,15 +590,15 @@ class Report
584
590
  context = context_for warning
585
591
  full_message = nil
586
592
 
587
- if OPTIONS[:message_limit] and
588
- OPTIONS[:message_limit] > 0 and
589
- message.length > OPTIONS[:message_limit]
593
+ if tracker.options[:message_limit] and
594
+ tracker.options[:message_limit] > 0 and
595
+ message.length > tracker.options[:message_limit]
590
596
 
591
597
  full_message = message
592
- message = message[0..OPTIONS[:message_limit]] << "..."
598
+ message = message[0..tracker.options[:message_limit]] << "..."
593
599
  end
594
600
 
595
- if context.empty?
601
+ if context.empty? and not full_message
596
602
  return CGI.escapeHTML(message)
597
603
  end
598
604
 
@@ -665,7 +671,7 @@ class Report
665
671
  [:model_warnings, "Model"], [:template_warnings, "Template"]].map do |meth, category|
666
672
 
667
673
  checks.send(meth).map do |w|
668
- next if w.confidence > OPTIONS[:min_confidence]
674
+ next if w.confidence > tracker.options[:min_confidence]
669
675
  line = w.line || 0
670
676
  w.warning_type.gsub!(/[^\w\s]/, ' ')
671
677
  "#{file_for w}\t#{line}\t#{w.warning_type}\t#{category}\t#{w.format_message}\t#{TEXT_CONFIDENCE[w.confidence]}"