lint_fu 0.5.0 → 0.5.3

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.
Files changed (39) hide show
  1. data/README.rdoc +4 -2
  2. data/bin/lint_fu +2 -86
  3. data/lib/lint_fu/blessing.rb +40 -0
  4. data/lib/lint_fu/checker.rb +49 -3
  5. data/lib/lint_fu/cli/command.rb +48 -0
  6. data/lib/lint_fu/cli/prune.rb +78 -0
  7. data/lib/lint_fu/cli/scan.rb +78 -0
  8. data/lib/lint_fu/cli.rb +52 -0
  9. data/lib/lint_fu/eidos.rb +35 -0
  10. data/lib/lint_fu/{model_element_builder.rb → eidos_builder.rb} +8 -3
  11. data/lib/lint_fu/eidos_container.rb +25 -0
  12. data/lib/lint_fu/file_range.rb +43 -0
  13. data/lib/lint_fu/mixins/sexp_instance_methods.rb +57 -9
  14. data/lib/lint_fu/parser.rb +1 -2
  15. data/lib/lint_fu/plugins/action_pack/controller_eidos.rb +7 -0
  16. data/lib/lint_fu/{action_pack/model_controller_builder.rb → plugins/action_pack/controller_eidos_builder.rb} +6 -6
  17. data/lib/lint_fu/plugins/action_pack.rb +2 -0
  18. data/lib/lint_fu/{active_record/model_model.rb → plugins/active_record/model_eidos.rb} +3 -3
  19. data/lib/lint_fu/{active_record/model_model_builder.rb → plugins/active_record/model_eidos_builder.rb} +17 -11
  20. data/lib/lint_fu/plugins/active_record.rb +2 -0
  21. data/lib/lint_fu/{rails → plugins/rails}/buggy_eager_load_checker.rb +6 -5
  22. data/lib/lint_fu/{rails/scan_builder.rb → plugins/rails/issue_builder.rb} +9 -16
  23. data/lib/lint_fu/plugins/rails/model_application.rb +21 -0
  24. data/lib/lint_fu/plugins/rails/model_application_factory.rb +31 -0
  25. data/lib/lint_fu/{rails → plugins/rails}/sql_injection_checker.rb +9 -5
  26. data/lib/lint_fu/{rails → plugins/rails}/unsafe_find_checker.rb +17 -30
  27. data/lib/lint_fu/plugins/rails.rb +29 -0
  28. data/lib/lint_fu/plugins.rb +11 -0
  29. data/lib/lint_fu/scan.rb +1 -49
  30. data/lib/lint_fu.rb +13 -8
  31. data/lint_fu.gemspec +10 -7
  32. metadata +140 -24
  33. data/lib/lint_fu/action_pack/model_controller.rb +0 -7
  34. data/lib/lint_fu/action_pack.rb +0 -2
  35. data/lib/lint_fu/active_record.rb +0 -2
  36. data/lib/lint_fu/model_element.rb +0 -48
  37. data/lib/lint_fu/rails/model_application.rb +0 -16
  38. data/lib/lint_fu/rails/model_application_builder.rb +0 -32
  39. data/lib/lint_fu/rails.rb +0 -6
@@ -0,0 +1,21 @@
1
+ module LintFu::Plugins
2
+ module Rails
3
+ class ModelApplication
4
+ attr_reader :fs_root
5
+
6
+ include LintFu::EidosContainer
7
+
8
+ def initialize(fs_root)
9
+ @fs_root = fs_root
10
+ end
11
+
12
+ def controllers
13
+ eide.select { |m| m.kind_of?(LintFu::Plugins::ActionPack::ControllerEidos) }
14
+ end
15
+
16
+ def models
17
+ eide.select { |m| m.kind_of?(LintFu::Plugins::ActiveRecord::ModelEidos) }
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,31 @@
1
+ module LintFu::Plugins
2
+ module Rails
3
+ class ModelApplicationFactory < LintFu::EidosBuilder
4
+ def initialize(fs_root)
5
+ super
6
+ @application = ModelApplication.new(fs_root)
7
+ self.eide << @application
8
+ end
9
+
10
+ def build
11
+ models_dir = File.join(@application.fs_root, 'app', 'models')
12
+ builder = LintFu::Plugins::ActiveRecord::ModelEidosBuilder.new
13
+ #TODO ensure the Rails app is using ActiveRecord
14
+ Dir.glob(File.join(models_dir, '**', '*.rb')).each do |f|
15
+ sexp = LintFu::Parser.parse_ruby(f)
16
+ builder.process(sexp)
17
+ end
18
+ builder.eide.each { |elem| @application.add_eidos(elem) }
19
+
20
+ controllers_dir = File.join(@application.fs_root, 'app', 'controllers')
21
+ builder = ActionPack::ControllerEidosBuilder.new
22
+ Dir.glob(File.join(controllers_dir, '**', '*.rb')).each do |f|
23
+ sexp = LintFu::Parser.parse_ruby(f)
24
+ sexp.file = f
25
+ builder.process(sexp)
26
+ end
27
+ builder.eide.each { |elem| @application.add_eidos(elem) }
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,6 +1,6 @@
1
- module LintFu
1
+ module LintFu::Plugins
2
2
  module Rails
3
- class SqlInjection < Issue
3
+ class SqlInjection < LintFu::Issue
4
4
  def initialize(scan, file, sexp, subject, confidence=1.0)
5
5
  super(scan, file, sexp, confidence)
6
6
  @subject = subject
@@ -44,7 +44,7 @@ EOF
44
44
 
45
45
  # Visit a Rails controller looking for ActiveRecord queries that contain interpolated
46
46
  # strings.
47
- class SqlInjectionChecker < Checker
47
+ class SqlInjectionChecker < LintFu::Checker
48
48
  FINDER_REGEXP = /^(find|first|all)(_or_initialize)?(_by_.*_id)?/
49
49
  SINK_OPTIONS = Set.new([:conditions, :select, :order, :group, :from, :include, :join])
50
50
 
@@ -55,30 +55,34 @@ EOF
55
55
  end
56
56
 
57
57
  def observe_class_begin(sexp)
58
+ super(sexp)
58
59
  @class_definition_scope.push sexp
59
60
  end
60
61
 
61
62
  def observe_class_end(sexp)
63
+ super(sexp)
62
64
  @class_definition_scope.pop
63
65
  end
64
66
 
65
67
  def observe_defn_begin(sexp)
66
-
68
+ super(sexp)
67
69
  @in_method = true
68
70
  end
69
71
 
70
72
  def observe_defn_end(sexp)
73
+ super(sexp)
71
74
  @in_method = false
72
75
  end
73
76
 
74
77
  def observe_call(sexp)
78
+ super(sexp)
75
79
  return if @class_definition_scope.empty? || !@in_method
76
80
 
77
81
  call = sexp[2].to_s
78
82
  arglist = sexp[3]
79
83
 
80
84
  tp = tainted_params(arglist)
81
- if finder?(call) && !tp.empty?
85
+ if finder?(call) && !tp.empty? && !suppressed?(UnsafeFind)
82
86
  scan.issues << SqlInjection.new(scan, self.file, sexp, tp[0].to_ruby_string, @base_confidence)
83
87
  end
84
88
  end
@@ -1,6 +1,6 @@
1
- module LintFu
1
+ module LintFu::Plugins
2
2
  module Rails
3
- class UnsafeFind < Issue
3
+ class UnsafeFind < LintFu::Issue
4
4
  def initialize(scan, file, sexp, subject)
5
5
  super(scan, file, sexp)
6
6
  @subject = subject
@@ -55,64 +55,51 @@ EOF
55
55
  # Visit a Rails controller looking for ActiveRecord finders being called in a way that
56
56
  # might allow an attacker to perform unauthorized operations on resources, e.g. creating,
57
57
  # updating or deleting someone else's records.
58
- class UnsafeFindChecker < Checker
58
+ class UnsafeFindChecker < LintFu::Checker
59
59
  FINDER_REGEXP = /^(find|first|all)(_or_initialize)?(_by_.*_id)?/
60
-
61
- #sexp:: s(:class, <class_name>, <superclass>, s(:scope, <class_definition>))
62
- def observe_class_begin(sexp)
63
- #TODO get rid of RightScale-specific assumption
64
- @in_admin_controller = !!(sexp[1].to_ruby_string =~ /^Admin/)
65
- end
66
-
67
- #sexp:: s(:class, <class_name>, <superclass>, s(:scope, <class_definition>))
68
- def observe_class_end(sexp)
69
- @in_admin_controller = false
70
- end
60
+ #TODO: make this tunable, also expose it to the user to make sure it's appropriate!!
61
+ SAFE_INSTANCE_METHODS = [:current_user, :current_account]
71
62
 
72
63
  #sexp:: s(:call, <target>, <method_name>, s(:arglist))
73
64
  def observe_call(sexp)
65
+ super(sexp)
74
66
  check_suspicious_finder(sexp)
75
67
  end
76
68
 
77
69
  protected
78
70
 
79
71
  def check_suspicious_finder(sexp)
80
- return if @in_admin_controller
81
-
82
72
  #sexp:: :call, <target>, <method_name>, <argslist...>
83
73
  if (sexp[1] != nil) && (sexp[1][0] == :const || sexp[1][0] == :colon2)
84
74
  name = sexp[1].to_ruby_string
85
75
  type = self.context.models.detect { |m| m.modeled_class_name == name }
86
76
  call = sexp[2].to_s
87
77
  params = sexp[3]
88
- if finder?(type, call) && !params.constant? && !sexp_contains_scope?(params)
78
+ if finder?(type, call) && !params.constant? &&
79
+ !safely_scoped?(params) && !suppressed?(UnsafeFind)
89
80
  scan.issues << UnsafeFind.new(scan, self.file, sexp, params.to_ruby_string)
90
81
  end
91
- end
82
+ end
92
83
  end
93
84
 
94
85
  def finder?(type, call)
95
- type.kind_of?(LintFu::ActiveRecord::ModelModel) &&
86
+ type.kind_of?(LintFu::Plugins::ActiveRecord::ModelEidos) &&
96
87
  ( call =~ FINDER_REGEXP || type.associations.has_key?(call) )
97
88
  end
98
89
 
99
- def sexp_contains_scope?(sexp)
90
+ def safely_scoped?(sexp)
100
91
  return false if !sexp.kind_of?(Sexp) || sexp.empty?
92
+ return true if sexp.constant?
101
93
 
102
- sexp_type = sexp[0]
103
-
104
- #If calling a method -- check to see if we're accessing a current_* method
105
- if (sexp_type == :call) && (sexp[1] == nil)
94
+ #Some local methods introduce safe scope
95
+ if (sexp[0] == :call)
106
96
  #TODO get rid of RightScale-specific assumptions
107
- return true if (sexp[2] == :current_user)
108
- return true if (sexp[2] == :current_account)
97
+ return true if sexp[1].nil? && SAFE_INSTANCE_METHODS.include?(sexp[2])
109
98
  end
110
99
 
111
- #Generic case: check all subexpressions of the sexp
100
+ #Generic case: check that all subexpressions of the sexp are safely scoped
112
101
  sexp.each do |subexp|
113
- if subexp.kind_of?(Sexp)
114
- return true if sexp_contains_scope?(subexp)
115
- end
102
+ return false if subexp.kind_of?(Sexp) && !safely_scoped?(subexp)
116
103
  end
117
104
 
118
105
  return false
@@ -0,0 +1,29 @@
1
+ require 'lint_fu/plugins/action_pack'
2
+ require 'lint_fu/plugins/active_record'
3
+
4
+ require 'lint_fu/plugins/rails/model_application'
5
+ require 'lint_fu/plugins/rails/model_application_factory'
6
+ require 'lint_fu/plugins/rails/buggy_eager_load_checker'
7
+ require 'lint_fu/plugins/rails/sql_injection_checker'
8
+ require 'lint_fu/plugins/rails/unsafe_find_checker'
9
+ require 'lint_fu/plugins/rails/issue_builder'
10
+
11
+ module LintFu::Plugins
12
+ module Rails
13
+ def self.applies_to?(dir)
14
+ File.exist?(File.join(dir, 'app')) &&
15
+ File.exist?(File.join(dir, 'config', 'environments')) &&
16
+ File.exist?(File.join(dir, 'config', 'environment.rb'))
17
+ end
18
+
19
+ def self.context_builder_for(dir)
20
+ return nil unless applies_to?(dir)
21
+ ModelApplicationFactory.new(dir)
22
+ end
23
+
24
+ def self.issue_builder_for(dir)
25
+ return nil unless applies_to?(dir)
26
+ IssueBuilder.new(dir)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,11 @@
1
+ #Ensure the module's namespace exists, so plugin authors can
2
+ #abbreviate the namespace decls in their files.
3
+ module LintFu
4
+ module Plugins
5
+ end
6
+ end
7
+
8
+ plugins_dir = File.expand_path('../plugins', __FILE__)
9
+ Dir[File.join(plugins_dir, '*.rb')].each do |file|
10
+ require file
11
+ end
data/lib/lint_fu/scan.rb CHANGED
@@ -2,10 +2,6 @@ module LintFu
2
2
  class ScanNotFinalized < Exception; end
3
3
 
4
4
  class Scan
5
- COMMENT = /^\s*#/
6
- VERBOSE_BLESSING_COMMENT = /#\s*(lint|security)\s*[-:]\s*not\s*a?n?\s*([a-z0-9 ]*) ?(as|because|;)\s*(.*)/i
7
- BLESSING_COMMENT = /#\s*(lint|security)\s*[-:]\s*not\s*a?n?\s*([a-z0-9 ]*)/i
8
-
9
5
  attr_reader :fs_root, :issues
10
6
 
11
7
  def initialize(fs_root)
@@ -14,51 +10,7 @@ module LintFu
14
10
  end
15
11
 
16
12
  def blessed?(issue)
17
- comments = preceeding_comments(issue.sexp)
18
- return false unless comments
19
-
20
- match = nil
21
- comments.each do |line|
22
- match = VERBOSE_BLESSING_COMMENT.match(line)
23
- match = BLESSING_COMMENT.match(line) unless match
24
- break if match
25
- end
26
-
27
- return false unless match
28
- blessed_issue_class = match[2].downcase.split(/\s+/).join('_').camelize
29
-
30
- # Determine whether the blessed issue class appears anywhere in the class hierarchy of
31
- # issue_class.
32
- klass = issue.class
33
- while klass
34
- return true if klass.name.index(blessed_issue_class)
35
- klass = klass.superclass
36
- end
37
-
38
- return false
13
+ issue.sexp.blessings.any? { |b| b.issue_class = issue.class }
39
14
  end
40
-
41
- def preceeding_comments(sexp)
42
- @file_contents ||= {}
43
- @file_contents[sexp.file] ||= File.readlines(sexp.file)
44
- cont = @file_contents[sexp.file]
45
-
46
- comments = ''
47
-
48
- max_line = sexp.line - 1 - 1
49
- max_line = 0 if max_line < 0
50
- min_line = max_line
51
-
52
- while cont[min_line] =~ COMMENT && min_line >= 0
53
- min_line -= 1
54
- end
55
-
56
- if cont[max_line] =~ COMMENT
57
- min_line +=1 unless min_line == max_line
58
- return cont[min_line..max_line]
59
- else
60
- return nil
61
- end
62
- end
63
15
  end
64
16
  end
data/lib/lint_fu.rb CHANGED
@@ -4,10 +4,11 @@ require 'digest/md5'
4
4
  require 'digest/sha1'
5
5
 
6
6
  # Activate the various gems we depend on
7
- require 'active_support'
7
+ require 'trollop'
8
8
  require 'ruby_parser'
9
9
  require 'sexp_processor'
10
10
  require 'ruby2ruby'
11
+ require 'active_support'
11
12
  require 'builder'
12
13
  require 'redcloth'
13
14
 
@@ -15,20 +16,24 @@ require 'redcloth'
15
16
  require 'lint_fu/mixins'
16
17
 
17
18
  # Core lint-fu sources
19
+ require 'lint_fu/file_range'
18
20
  require 'lint_fu/parser'
19
- require 'lint_fu/model_element'
20
- require 'lint_fu/model_element_builder'
21
+ require 'lint_fu/eidos'
22
+ require 'lint_fu/eidos_container'
23
+ require 'lint_fu/eidos_builder'
21
24
  require 'lint_fu/source_control_provider'
22
25
  require 'lint_fu/issue'
26
+ require 'lint_fu/blessing'
23
27
  require 'lint_fu/checker'
24
28
  require 'lint_fu/visitor'
25
29
  require 'lint_fu/scan'
26
30
  require 'lint_fu/report'
27
31
 
28
- # lint-fu source control providers
32
+ # source control providers
29
33
  require 'lint_fu/source_control/git'
30
34
 
31
- # lint-fu plugins
32
- require 'lint_fu/active_record'
33
- require 'lint_fu/action_pack'
34
- require 'lint_fu/rails'
35
+ # plugins
36
+ require 'lint_fu/plugins'
37
+
38
+ # command line interface
39
+ require 'lint_fu/cli'
data/lint_fu.gemspec CHANGED
@@ -1,4 +1,4 @@
1
- # -*- encoding: utf-8 -*-
1
+ # -*- mode: ruby; encoding: utf-8 -*-
2
2
 
3
3
  require 'rubygems'
4
4
 
@@ -7,7 +7,7 @@ spec = Gem::Specification.new do |s|
7
7
  s.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
8
8
 
9
9
  s.name = 'lint_fu'
10
- s.version = '0.5.0'
10
+ s.version = '0.5.3'
11
11
  s.date = '2011-02-19'
12
12
 
13
13
  s.authors = ['Tony Spataro']
@@ -17,10 +17,18 @@ spec = Gem::Specification.new do |s|
17
17
  s.summary = %q{Security scanner that performs static analysis of Ruby code.}
18
18
  s.description = %q{This tool helps identify bugs in your code. It is Rails-centric but its modular design allows support for other application frameworks.}
19
19
 
20
+ s.add_runtime_dependency('trollop', [">= 1.16.0"])
20
21
  s.add_runtime_dependency('ruby_parser', ["~> 2.0"])
21
22
  s.add_runtime_dependency('ruby2ruby', ["~> 1.2"])
22
23
  s.add_runtime_dependency('activesupport', ["~> 2.3"])
24
+ s.add_runtime_dependency('builder', ["~> 2.1"])
25
+ s.add_runtime_dependency('RedCloth', ["~> 4.2"])
23
26
 
27
+ s.add_development_dependency('rake', [">= 0.8.7"])
28
+ s.add_development_dependency('ruby-debug', [">= 0.10.3"])
29
+ s.add_development_dependency('rspec', ["~> 1.3"])
30
+ s.add_development_dependency('flexmock', ["~> 0.8"])
31
+
24
32
  s.executables = ["lint_fu"]
25
33
 
26
34
  candidates = ['lint_fu.gemspec', 'MIT-LICENSE', 'README.rdoc'] +
@@ -28,8 +36,3 @@ spec = Gem::Specification.new do |s|
28
36
  Dir['bin/*']
29
37
  s.files = candidates.sort
30
38
  end
31
-
32
- if $PROGRAM_NAME == __FILE__
33
- Gem.manage_gems if Gem::RubyGemsVersion.to_f < 1.0
34
- Gem::Builder.new(spec).build
35
- end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lint_fu
3
3
  version: !ruby/object:Gem::Version
4
- hash: 11
4
+ hash: 13
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 5
9
- - 0
10
- version: 0.5.0
9
+ - 3
10
+ version: 0.5.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Tony Spataro
@@ -19,9 +19,25 @@ date: 2011-02-19 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
- name: ruby_parser
22
+ name: trollop
23
23
  prerelease: false
24
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 87
30
+ segments:
31
+ - 1
32
+ - 16
33
+ - 0
34
+ version: 1.16.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: ruby_parser
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
25
41
  none: false
26
42
  requirements:
27
43
  - - ~>
@@ -32,11 +48,11 @@ dependencies:
32
48
  - 0
33
49
  version: "2.0"
34
50
  type: :runtime
35
- version_requirements: *id001
51
+ version_requirements: *id002
36
52
  - !ruby/object:Gem::Dependency
37
53
  name: ruby2ruby
38
54
  prerelease: false
39
- requirement: &id002 !ruby/object:Gem::Requirement
55
+ requirement: &id003 !ruby/object:Gem::Requirement
40
56
  none: false
41
57
  requirements:
42
58
  - - ~>
@@ -47,11 +63,11 @@ dependencies:
47
63
  - 2
48
64
  version: "1.2"
49
65
  type: :runtime
50
- version_requirements: *id002
66
+ version_requirements: *id003
51
67
  - !ruby/object:Gem::Dependency
52
68
  name: activesupport
53
69
  prerelease: false
54
- requirement: &id003 !ruby/object:Gem::Requirement
70
+ requirement: &id004 !ruby/object:Gem::Requirement
55
71
  none: false
56
72
  requirements:
57
73
  - - ~>
@@ -62,7 +78,99 @@ dependencies:
62
78
  - 3
63
79
  version: "2.3"
64
80
  type: :runtime
65
- version_requirements: *id003
81
+ version_requirements: *id004
82
+ - !ruby/object:Gem::Dependency
83
+ name: builder
84
+ prerelease: false
85
+ requirement: &id005 !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ~>
89
+ - !ruby/object:Gem::Version
90
+ hash: 1
91
+ segments:
92
+ - 2
93
+ - 1
94
+ version: "2.1"
95
+ type: :runtime
96
+ version_requirements: *id005
97
+ - !ruby/object:Gem::Dependency
98
+ name: RedCloth
99
+ prerelease: false
100
+ requirement: &id006 !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ~>
104
+ - !ruby/object:Gem::Version
105
+ hash: 31
106
+ segments:
107
+ - 4
108
+ - 2
109
+ version: "4.2"
110
+ type: :runtime
111
+ version_requirements: *id006
112
+ - !ruby/object:Gem::Dependency
113
+ name: rake
114
+ prerelease: false
115
+ requirement: &id007 !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ hash: 49
121
+ segments:
122
+ - 0
123
+ - 8
124
+ - 7
125
+ version: 0.8.7
126
+ type: :development
127
+ version_requirements: *id007
128
+ - !ruby/object:Gem::Dependency
129
+ name: ruby-debug
130
+ prerelease: false
131
+ requirement: &id008 !ruby/object:Gem::Requirement
132
+ none: false
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ hash: 49
137
+ segments:
138
+ - 0
139
+ - 10
140
+ - 3
141
+ version: 0.10.3
142
+ type: :development
143
+ version_requirements: *id008
144
+ - !ruby/object:Gem::Dependency
145
+ name: rspec
146
+ prerelease: false
147
+ requirement: &id009 !ruby/object:Gem::Requirement
148
+ none: false
149
+ requirements:
150
+ - - ~>
151
+ - !ruby/object:Gem::Version
152
+ hash: 9
153
+ segments:
154
+ - 1
155
+ - 3
156
+ version: "1.3"
157
+ type: :development
158
+ version_requirements: *id009
159
+ - !ruby/object:Gem::Dependency
160
+ name: flexmock
161
+ prerelease: false
162
+ requirement: &id010 !ruby/object:Gem::Requirement
163
+ none: false
164
+ requirements:
165
+ - - ~>
166
+ - !ruby/object:Gem::Version
167
+ hash: 27
168
+ segments:
169
+ - 0
170
+ - 8
171
+ version: "0.8"
172
+ type: :development
173
+ version_requirements: *id010
66
174
  description: This tool helps identify bugs in your code. It is Rails-centric but its modular design allows support for other application frameworks.
67
175
  email: code@tracker.xeger.net
68
176
  executables:
@@ -76,28 +184,36 @@ files:
76
184
  - README.rdoc
77
185
  - bin/lint_fu
78
186
  - lib/lint_fu.rb
79
- - lib/lint_fu/action_pack.rb
80
- - lib/lint_fu/action_pack/model_controller.rb
81
- - lib/lint_fu/action_pack/model_controller_builder.rb
82
- - lib/lint_fu/active_record.rb
83
- - lib/lint_fu/active_record/model_model.rb
84
- - lib/lint_fu/active_record/model_model_builder.rb
187
+ - lib/lint_fu/blessing.rb
85
188
  - lib/lint_fu/checker.rb
189
+ - lib/lint_fu/cli.rb
190
+ - lib/lint_fu/cli/command.rb
191
+ - lib/lint_fu/cli/prune.rb
192
+ - lib/lint_fu/cli/scan.rb
193
+ - lib/lint_fu/eidos.rb
194
+ - lib/lint_fu/eidos_builder.rb
195
+ - lib/lint_fu/eidos_container.rb
196
+ - lib/lint_fu/file_range.rb
86
197
  - lib/lint_fu/issue.rb
87
198
  - lib/lint_fu/mixins.rb
88
199
  - lib/lint_fu/mixins/file_class_methods.rb
89
200
  - lib/lint_fu/mixins/sexp_instance_methods.rb
90
201
  - lib/lint_fu/mixins/symbol_instance_methods.rb
91
- - lib/lint_fu/model_element.rb
92
- - lib/lint_fu/model_element_builder.rb
93
202
  - lib/lint_fu/parser.rb
94
- - lib/lint_fu/rails.rb
95
- - lib/lint_fu/rails/buggy_eager_load_checker.rb
96
- - lib/lint_fu/rails/model_application.rb
97
- - lib/lint_fu/rails/model_application_builder.rb
98
- - lib/lint_fu/rails/scan_builder.rb
99
- - lib/lint_fu/rails/sql_injection_checker.rb
100
- - lib/lint_fu/rails/unsafe_find_checker.rb
203
+ - lib/lint_fu/plugins.rb
204
+ - lib/lint_fu/plugins/action_pack.rb
205
+ - lib/lint_fu/plugins/action_pack/controller_eidos.rb
206
+ - lib/lint_fu/plugins/action_pack/controller_eidos_builder.rb
207
+ - lib/lint_fu/plugins/active_record.rb
208
+ - lib/lint_fu/plugins/active_record/model_eidos.rb
209
+ - lib/lint_fu/plugins/active_record/model_eidos_builder.rb
210
+ - lib/lint_fu/plugins/rails.rb
211
+ - lib/lint_fu/plugins/rails/buggy_eager_load_checker.rb
212
+ - lib/lint_fu/plugins/rails/issue_builder.rb
213
+ - lib/lint_fu/plugins/rails/model_application.rb
214
+ - lib/lint_fu/plugins/rails/model_application_factory.rb
215
+ - lib/lint_fu/plugins/rails/sql_injection_checker.rb
216
+ - lib/lint_fu/plugins/rails/unsafe_find_checker.rb
101
217
  - lib/lint_fu/report.rb
102
218
  - lib/lint_fu/scan.rb
103
219
  - lib/lint_fu/source_control/git.rb