Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 186 lines (131 sloc) 6.586 kB
808feb0 @dmajda Initial commit
dmajda authored
1 Scanny
2 ======
3
4 Scanny is a Ruby on Rails security scanner. It parses Ruby files, looks for various suspicious patterns in them (by traversing the AST) and produces a report. Scanny aims to be simple (it does one thing well) and extensible (it is easy to define new patterns).
5
95fa062 @dmajda Improve README.md
dmajda authored
6 **This is currently work in progress and it's probably not useful yet.**
808feb0 @dmajda Initial commit
dmajda authored
7
95fa062 @dmajda Improve README.md
dmajda authored
8 Installation
9 ------------
808feb0 @dmajda Initial commit
dmajda authored
10
9e753da @dmajda Tweak README.md
dmajda authored
11 You need to install the current development version of [Rubinius](http://rubini.us/) first. You can then install Scanny:
808feb0 @dmajda Initial commit
dmajda authored
12
9e753da @dmajda Tweak README.md
dmajda authored
13 $ gem install scanny
95fa062 @dmajda Improve README.md
dmajda authored
14
15 Usage
16 -----
17
9e753da @dmajda Tweak README.md
dmajda authored
18 To scan one or more Ruby file, use the `scanny` command and pass the files to scan as arguments. Scanny will check the files and print a nice report:
95fa062 @dmajda Improve README.md
dmajda authored
19
20 $ cat bad.rb
21 `ls #{ARGV[1]}`
9e753da @dmajda Tweak README.md
dmajda authored
22 $ scanny bad.rb
95fa062 @dmajda Improve README.md
dmajda authored
23 bad.rb [2 checks done | 2 nodes inspected | 1 issues]
24 - [high] bad.rb:1: Backticks and %x{...} pass the executed command through shell expansion. (CWE-88, CWE-78)
25
26 Found 1 issues.
27
19b1f99 @LTe Add information about rake-task do README
LTe authored
28 Rake task
29 ---------
30
31 To create scanny rake task you need to edit Rakefile.
32
33 ```ruby
34 require "scanny/rake_task"
35
36 Scanny::RakeTask.new do |t|
37 t.name = "scanny" # name of rake-task
38 t.include = "./custom/checks" # directory with custom checks
39 t.disable = "HTTPRedirectCheck" # checks to disable
40 t.format = :stdout # output format
41 t.strict = true # scanny strict mode
42 t.path = "./custom/app" # path to scan
43 t.fail_on_error = true # raise exception on error
0cf9ccb @LTe Update README with ruby_mode
LTe authored
44 t.ruby_mode = "18" # ruby parser mode (default 19)
19b1f99 @LTe Add information about rake-task do README
LTe authored
45 end
46 ```
47
8a92763 @LTe Add information about Travis CI
LTe authored
48 CI (Continuous Integration)
49 ---------------------------
50
eff063e @LTe Add Jenkins to README
LTe authored
51 ### Common for all CLI
8a92763 @LTe Add information about Travis CI
LTe authored
52
53 * Add to ```Gemfile``` scanny gem
54
55 ```ruby
56 gem 'scanny'
57 ```
58
59 * Create [Rake task](https://github.com/openSUSE/scanny#rake-task).
60
61 ```ruby
62 Scanny::RakeTask.new do |t|
63 t.format = :stdout # you will see output on travis website
64 t.fail_on_error = false # security errors should not break build
65 end
66 ```
67
eff063e @LTe Add Jenkins to README
LTe authored
68 ### Travis
69
8a92763 @LTe Add information about Travis CI
LTe authored
70 * Update your ```.travis.yml``` file. You need add ```before_script``` section.
71
72 ```yaml
73 before_script:
74 - test -s "$HOME/.rvm/scripts/rvm" && source "$HOME/.rvm/scripts/rvm"
75 - rvm rbx-19mode
76 - bundle install
77 - bundle exec rake scanny
78 - rvm $TRAVIS_RUBY_VERSION
79 ```
80
eff063e @LTe Add Jenkins to README
LTe authored
81 ### Jenkins
82
83 * Add build step
84
85 ```
86 bash -l -c '
87 rvm rbx-head &&
88 rvm gemset create scanny &&
89 rvm gemset use scanny &&
90 bundle install &&
91 bundle exec rake scanny'
92 ```
93
94 * Install [Log Parser Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Log+Parser+Plugin) for Jenkins
95 * Create rules file
96
97 ```ruby
98 # /var/lib/jenkins/rules
99
100 info /- \[info\]/
101 warning /- \[low\]/
102 error /- \[(medium|high)\]/
103 ```
104
105 * Go to ```Manage Jenkins > Configure System > Console Output Parsing```.
106 Add path to rules with in **Parsing Rules File** field
107
108 * Go to and check ```[Project] > Configure > Console output (build log) parsing```
109 * Select proper **Select Parsing Rules**
110 * Warnings you can find in ```[Build] > Parsed Console Output```
111
8a92763 @LTe Add information about Travis CI
LTe authored
112
03ee8ff @dmajda Add section about writing new checks to README.md
dmajda authored
113 Writing New Checks
114 ------------------
115 Internally, Scanny consists of multiple *checks*, each responsible for finding and reporting one suspicious pattern in the code. You can easily extend Scanny by writing new checks.
116
117 The checks are loaded automatically from files in the `lib/scanny/checks` directory. Let's look how a simple check may look like:
118
119 module Scanny
120 module Checks
121 # Finds all invocations of "boo" and "moo" methods.
122 class BooMooCheck < Check
123 def pattern
124 'Send<name = :boo | :moo> | SendWithArguments<name = :boo | :moo>'
125 end
126
127 def check(node)
128 issue :high, "The \"#{node.name}\" method indicates wandering cows in the code.",
129 :cwe => 999
130 end
131 end
132 end
133 end
134
135 Checks are subclasses of the `Scanny::Checks::Check` class and they implement two methods: `pattern` and `check`.
136
137 ### The `pattern` method
138
139 The `pattern` method returns a [Machete](https://github.com/openSUSE/machete) pattern describing Rubinius AST nodes this check is interested in. See [Machete documentation](https://github.com/openSUSE/machete/blob/master/README.md) to learn about the pattern syntax.
140
141 **Tip:** When creating a check pattern it's often useful to inspect how Rubinius transforms some Ruby constructs into AST nodes. You can do this using the `to_ast` method:
142
143 '42'.to_ast # => #<Rubinius::AST::FixnumLiteral:0x36fc @value=42 @line=1>
144
145 ### The `check` method
146
147 The `check` method will be called on all AST nodes in the scanned files matched by the pattern returned by the `pattern` method. It will be passed the suspicious node. It can perform additional checks on it and report an issue if the node really is problematic.
148
149 Issues are reported using the `issue` method. As its arguments it accepts issue impact level (`:info`, `:low`, `:medium` or `:high`) and a message for the user, optionally followed by an options hash. The only currently implemented option is `:cwe`, which allows associating the issue with a [CWE number](http://www.cvedetails.com/cwe-definitions.php) (or multiple numbers if you pass an array).
150
151 ### Tests
152
153 Each check should be tested. The tests are written in RSpec and they are stored in the `spec/scanny/checks` directory. This is how a test for our sample check may look like:
154
155 require "spec_helper"
156
157 module Scanny::Checks
158 describe BooMooCheck do
159 it "reports \"boo\" correctly" do
160 @runner.should check('boo').with_issue(
161 issue(:high, "The \"boo\" method indicates wandering cows in the code.", 999)
162 )
163 end
164
165 it "reports \"moo\" correctly" do
166 @runner.should check('moo').with_issue(
167 issue(:high, "The \"moo\" method indicates wandering cows in the code.", 999)
168 )
169 end
170 end
171 end
172
173 Aim to create as simple test cases as possible. Also test different kinds of issues separately. See the existing tests to learn how more complex checks are tested.
174
9e753da @dmajda Tweak README.md
dmajda authored
175 Compatibility
176 -------------
177
178 Scanny requires Rubinius 1.9 mode to run.
179
95fa062 @dmajda Improve README.md
dmajda authored
180 Acknowledgement
181 ---------------
182
183 The tool was written as a replacement of Thomas Biege's [Ruby on Rails scanner](http://gitorious.org/code-scanner/ror-sec-scanner/) which was used internally at [SUSE](http://www.suse.com/). This tool needed replacement because it look for suspicious patterns using just regular expressions, which is very rough and has expressivity problems with more complex patterns.
184
185 The original AST parsing and checking code was copied and adapted from [Roodi](http://roodi.rubyforge.org/), a tool for detecting Ruby code design issues.
Something went wrong with that request. Please try again.