brakeman-lib 3.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGES +872 -0
- data/FEATURES +16 -0
- data/README.md +169 -0
- data/WARNING_TYPES +95 -0
- data/bin/brakeman +89 -0
- data/lib/brakeman.rb +495 -0
- data/lib/brakeman/app_tree.rb +161 -0
- data/lib/brakeman/brakeman.rake +17 -0
- data/lib/brakeman/call_index.rb +219 -0
- data/lib/brakeman/checks.rb +191 -0
- data/lib/brakeman/checks/base_check.rb +518 -0
- data/lib/brakeman/checks/check_basic_auth.rb +88 -0
- data/lib/brakeman/checks/check_basic_auth_timing_attack.rb +33 -0
- data/lib/brakeman/checks/check_content_tag.rb +160 -0
- data/lib/brakeman/checks/check_create_with.rb +75 -0
- data/lib/brakeman/checks/check_cross_site_scripting.rb +385 -0
- data/lib/brakeman/checks/check_default_routes.rb +86 -0
- data/lib/brakeman/checks/check_deserialize.rb +57 -0
- data/lib/brakeman/checks/check_detailed_exceptions.rb +55 -0
- data/lib/brakeman/checks/check_digest_dos.rb +38 -0
- data/lib/brakeman/checks/check_dynamic_finders.rb +49 -0
- data/lib/brakeman/checks/check_escape_function.rb +21 -0
- data/lib/brakeman/checks/check_evaluation.rb +36 -0
- data/lib/brakeman/checks/check_execute.rb +167 -0
- data/lib/brakeman/checks/check_file_access.rb +63 -0
- data/lib/brakeman/checks/check_file_disclosure.rb +35 -0
- data/lib/brakeman/checks/check_filter_skipping.rb +31 -0
- data/lib/brakeman/checks/check_forgery_setting.rb +74 -0
- data/lib/brakeman/checks/check_header_dos.rb +31 -0
- data/lib/brakeman/checks/check_i18n_xss.rb +48 -0
- data/lib/brakeman/checks/check_jruby_xml.rb +38 -0
- data/lib/brakeman/checks/check_json_encoding.rb +47 -0
- data/lib/brakeman/checks/check_json_parsing.rb +107 -0
- data/lib/brakeman/checks/check_link_to.rb +132 -0
- data/lib/brakeman/checks/check_link_to_href.rb +115 -0
- data/lib/brakeman/checks/check_mail_to.rb +49 -0
- data/lib/brakeman/checks/check_mass_assignment.rb +198 -0
- data/lib/brakeman/checks/check_mime_type_dos.rb +39 -0
- data/lib/brakeman/checks/check_model_attr_accessible.rb +55 -0
- data/lib/brakeman/checks/check_model_attributes.rb +119 -0
- data/lib/brakeman/checks/check_model_serialize.rb +67 -0
- data/lib/brakeman/checks/check_nested_attributes.rb +38 -0
- data/lib/brakeman/checks/check_nested_attributes_bypass.rb +58 -0
- data/lib/brakeman/checks/check_number_to_currency.rb +74 -0
- data/lib/brakeman/checks/check_quote_table_name.rb +40 -0
- data/lib/brakeman/checks/check_redirect.rb +215 -0
- data/lib/brakeman/checks/check_regex_dos.rb +69 -0
- data/lib/brakeman/checks/check_render.rb +92 -0
- data/lib/brakeman/checks/check_render_dos.rb +37 -0
- data/lib/brakeman/checks/check_render_inline.rb +54 -0
- data/lib/brakeman/checks/check_response_splitting.rb +21 -0
- data/lib/brakeman/checks/check_route_dos.rb +42 -0
- data/lib/brakeman/checks/check_safe_buffer_manipulation.rb +31 -0
- data/lib/brakeman/checks/check_sanitize_methods.rb +79 -0
- data/lib/brakeman/checks/check_secrets.rb +40 -0
- data/lib/brakeman/checks/check_select_tag.rb +60 -0
- data/lib/brakeman/checks/check_select_vulnerability.rb +60 -0
- data/lib/brakeman/checks/check_send.rb +48 -0
- data/lib/brakeman/checks/check_send_file.rb +19 -0
- data/lib/brakeman/checks/check_session_manipulation.rb +36 -0
- data/lib/brakeman/checks/check_session_settings.rb +170 -0
- data/lib/brakeman/checks/check_simple_format.rb +59 -0
- data/lib/brakeman/checks/check_single_quotes.rb +101 -0
- data/lib/brakeman/checks/check_skip_before_filter.rb +60 -0
- data/lib/brakeman/checks/check_sql.rb +660 -0
- data/lib/brakeman/checks/check_sql_cves.rb +101 -0
- data/lib/brakeman/checks/check_ssl_verify.rb +49 -0
- data/lib/brakeman/checks/check_strip_tags.rb +89 -0
- data/lib/brakeman/checks/check_symbol_dos.rb +64 -0
- data/lib/brakeman/checks/check_symbol_dos_cve.rb +30 -0
- data/lib/brakeman/checks/check_translate_bug.rb +45 -0
- data/lib/brakeman/checks/check_unsafe_reflection.rb +51 -0
- data/lib/brakeman/checks/check_unscoped_find.rb +41 -0
- data/lib/brakeman/checks/check_validation_regex.rb +116 -0
- data/lib/brakeman/checks/check_weak_hash.rb +151 -0
- data/lib/brakeman/checks/check_without_protection.rb +80 -0
- data/lib/brakeman/checks/check_xml_dos.rb +51 -0
- data/lib/brakeman/checks/check_yaml_parsing.rb +121 -0
- data/lib/brakeman/differ.rb +66 -0
- data/lib/brakeman/file_parser.rb +50 -0
- data/lib/brakeman/format/style.css +133 -0
- data/lib/brakeman/options.rb +301 -0
- data/lib/brakeman/parsers/rails2_erubis.rb +6 -0
- data/lib/brakeman/parsers/rails2_xss_plugin_erubis.rb +48 -0
- data/lib/brakeman/parsers/rails3_erubis.rb +74 -0
- data/lib/brakeman/parsers/template_parser.rb +89 -0
- data/lib/brakeman/processor.rb +102 -0
- data/lib/brakeman/processors/alias_processor.rb +1013 -0
- data/lib/brakeman/processors/base_processor.rb +277 -0
- data/lib/brakeman/processors/config_processor.rb +14 -0
- data/lib/brakeman/processors/controller_alias_processor.rb +273 -0
- data/lib/brakeman/processors/controller_processor.rb +326 -0
- data/lib/brakeman/processors/erb_template_processor.rb +80 -0
- data/lib/brakeman/processors/erubis_template_processor.rb +104 -0
- data/lib/brakeman/processors/gem_processor.rb +57 -0
- data/lib/brakeman/processors/haml_template_processor.rb +190 -0
- data/lib/brakeman/processors/lib/basic_processor.rb +37 -0
- data/lib/brakeman/processors/lib/find_all_calls.rb +223 -0
- data/lib/brakeman/processors/lib/find_call.rb +183 -0
- data/lib/brakeman/processors/lib/find_return_value.rb +134 -0
- data/lib/brakeman/processors/lib/processor_helper.rb +75 -0
- data/lib/brakeman/processors/lib/rails2_config_processor.rb +145 -0
- data/lib/brakeman/processors/lib/rails2_route_processor.rb +313 -0
- data/lib/brakeman/processors/lib/rails3_config_processor.rb +132 -0
- data/lib/brakeman/processors/lib/rails3_route_processor.rb +308 -0
- data/lib/brakeman/processors/lib/render_helper.rb +181 -0
- data/lib/brakeman/processors/lib/render_path.rb +107 -0
- data/lib/brakeman/processors/lib/route_helper.rb +68 -0
- data/lib/brakeman/processors/lib/safe_call_helper.rb +16 -0
- data/lib/brakeman/processors/library_processor.rb +119 -0
- data/lib/brakeman/processors/model_processor.rb +191 -0
- data/lib/brakeman/processors/output_processor.rb +171 -0
- data/lib/brakeman/processors/route_processor.rb +17 -0
- data/lib/brakeman/processors/slim_template_processor.rb +107 -0
- data/lib/brakeman/processors/template_alias_processor.rb +116 -0
- data/lib/brakeman/processors/template_processor.rb +74 -0
- data/lib/brakeman/report.rb +78 -0
- data/lib/brakeman/report/config/remediation.yml +71 -0
- data/lib/brakeman/report/ignore/config.rb +135 -0
- data/lib/brakeman/report/ignore/interactive.rb +311 -0
- data/lib/brakeman/report/renderer.rb +24 -0
- data/lib/brakeman/report/report_base.rb +286 -0
- data/lib/brakeman/report/report_codeclimate.rb +70 -0
- data/lib/brakeman/report/report_csv.rb +55 -0
- data/lib/brakeman/report/report_hash.rb +23 -0
- data/lib/brakeman/report/report_html.rb +216 -0
- data/lib/brakeman/report/report_json.rb +42 -0
- data/lib/brakeman/report/report_markdown.rb +156 -0
- data/lib/brakeman/report/report_table.rb +107 -0
- data/lib/brakeman/report/report_tabs.rb +17 -0
- data/lib/brakeman/report/templates/controller_overview.html.erb +22 -0
- data/lib/brakeman/report/templates/controller_warnings.html.erb +21 -0
- data/lib/brakeman/report/templates/error_overview.html.erb +29 -0
- data/lib/brakeman/report/templates/header.html.erb +58 -0
- data/lib/brakeman/report/templates/ignored_warnings.html.erb +25 -0
- data/lib/brakeman/report/templates/model_warnings.html.erb +21 -0
- data/lib/brakeman/report/templates/overview.html.erb +38 -0
- data/lib/brakeman/report/templates/security_warnings.html.erb +23 -0
- data/lib/brakeman/report/templates/template_overview.html.erb +21 -0
- data/lib/brakeman/report/templates/view_warnings.html.erb +34 -0
- data/lib/brakeman/report/templates/warning_overview.html.erb +17 -0
- data/lib/brakeman/rescanner.rb +483 -0
- data/lib/brakeman/scanner.rb +317 -0
- data/lib/brakeman/tracker.rb +347 -0
- data/lib/brakeman/tracker/collection.rb +93 -0
- data/lib/brakeman/tracker/config.rb +101 -0
- data/lib/brakeman/tracker/constants.rb +101 -0
- data/lib/brakeman/tracker/controller.rb +161 -0
- data/lib/brakeman/tracker/library.rb +17 -0
- data/lib/brakeman/tracker/model.rb +90 -0
- data/lib/brakeman/tracker/template.rb +33 -0
- data/lib/brakeman/util.rb +481 -0
- data/lib/brakeman/version.rb +3 -0
- data/lib/brakeman/warning.rb +255 -0
- data/lib/brakeman/warning_codes.rb +111 -0
- data/lib/ruby_parser/bm_sexp.rb +610 -0
- data/lib/ruby_parser/bm_sexp_processor.rb +116 -0
- metadata +362 -0
data/FEATURES
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
Can detect:
|
2
|
+
-Possibly unescaped model attributes or parameters in views (Cross Site Scripting)
|
3
|
+
-Bad string interpolation in calls to Model.find, Model.last, Model.first, etc., as well as chained calls (SQL Injection)
|
4
|
+
-String interpolation in find_by_sql (SQL Injection)
|
5
|
+
-String interpolation or params in calls to system, exec, and syscall and `` (Command Injection)
|
6
|
+
-Unrestricted mass assignments
|
7
|
+
-Global restriction of mass assignment
|
8
|
+
-Missing call to protect_from_forgery in ApplicationController (CSRF protection)
|
9
|
+
-Default routes, per-controller and globally
|
10
|
+
-Redirects based on params (probably too broad currently)
|
11
|
+
-Validation regexes not using \A and \z
|
12
|
+
-Calls to render with dynamic paths
|
13
|
+
|
14
|
+
General capabilities:
|
15
|
+
-Search for method calls based on target class and/or method name
|
16
|
+
-Determine 'output' of templates using ERB, Erubis, or HAML. Can handle automatic escaping
|
data/README.md
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
[![Brakeman Logo](http://brakemanscanner.org/images/logo_medium.png)](http://brakemanscanner.org/)
|
2
|
+
[![Brakeman Pro Logo](https://brakemanpro.com/images/bmp_square_white.png)](https://brakemanpro.com)
|
3
|
+
|
4
|
+
[![Build Status](https://travis-ci.org/presidentbeef/brakeman.svg?branch=master)](https://travis-ci.org/presidentbeef/brakeman)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/presidentbeef/brakeman/badges/gpa.svg)](https://codeclimate.com/github/presidentbeef/brakeman)
|
6
|
+
[![Test Coverage](https://codeclimate.com/github/presidentbeef/brakeman/badges/coverage.svg)](https://codeclimate.com/github/presidentbeef/brakeman/coverage)
|
7
|
+
[![Gitter](https://badges.gitter.im/presidentbeef/brakeman.svg)](https://gitter.im/presidentbeef/brakeman)
|
8
|
+
|
9
|
+
# Brakeman
|
10
|
+
|
11
|
+
Brakeman is an open source static analysis tool which checks Ruby on Rails applications for security vulnerabilities.
|
12
|
+
|
13
|
+
Check out [Brakeman Pro](https://brakemanpro.com/) if you are looking for a commercially-supported version with a GUI and advanced features.
|
14
|
+
|
15
|
+
# Installation
|
16
|
+
|
17
|
+
Using RubyGems:
|
18
|
+
|
19
|
+
gem install brakeman
|
20
|
+
|
21
|
+
Using Bundler:
|
22
|
+
|
23
|
+
group :development do
|
24
|
+
gem 'brakeman', :require => false
|
25
|
+
end
|
26
|
+
|
27
|
+
# Usage
|
28
|
+
|
29
|
+
From a Rails application's root directory:
|
30
|
+
|
31
|
+
brakeman
|
32
|
+
|
33
|
+
Outside of Rails root:
|
34
|
+
|
35
|
+
brakeman /path/to/rails/application
|
36
|
+
|
37
|
+
# Compatibility
|
38
|
+
|
39
|
+
Brakeman works with Rails 2.x, 3.x, and 4.x.
|
40
|
+
|
41
|
+
# Basic Options
|
42
|
+
|
43
|
+
For a full list of options, use `brakeman --help` or see the [OPTIONS.md](OPTIONS.md) file.
|
44
|
+
|
45
|
+
To specify an output file for the results:
|
46
|
+
|
47
|
+
brakeman -o output_file
|
48
|
+
|
49
|
+
The output format is determined by the file extension or by using the `-f` option. Current options are: `text`, `html`, `tabs`, `json`, `markdown`, `csv`, and `codeclimate`.
|
50
|
+
|
51
|
+
Multiple output files can be specified:
|
52
|
+
|
53
|
+
brakeman -o output.html -o output.json
|
54
|
+
|
55
|
+
To suppress informational warnings and just output the report:
|
56
|
+
|
57
|
+
brakeman -q
|
58
|
+
|
59
|
+
Note all Brakeman output except reports are sent to stderr, making it simple to redirect stdout to a file and just get the report.
|
60
|
+
|
61
|
+
To see all kinds of debugging information:
|
62
|
+
|
63
|
+
brakeman -d
|
64
|
+
|
65
|
+
Specific checks can be skipped, if desired. The name needs to be the correct case. For example, to skip looking for default routes (`DefaultRoutes`):
|
66
|
+
|
67
|
+
brakeman -x DefaultRoutes
|
68
|
+
|
69
|
+
Multiple checks should be separated by a comma:
|
70
|
+
|
71
|
+
brakeman -x DefaultRoutes,Redirect
|
72
|
+
|
73
|
+
To do the opposite and only run a certain set of tests:
|
74
|
+
|
75
|
+
brakeman -t SQL,ValidationRegex
|
76
|
+
|
77
|
+
If Brakeman is running a bit slow, try
|
78
|
+
|
79
|
+
brakeman --faster
|
80
|
+
|
81
|
+
This will disable some features, but will probably be much faster (currently it is the same as `--skip-libs --no-branching`). *WARNING*: This may cause Brakeman to miss some vulnerabilities.
|
82
|
+
|
83
|
+
By default, Brakeman will return 0 as an exit code unless something went very wrong. To return an error code when warnings were found:
|
84
|
+
|
85
|
+
brakeman -z
|
86
|
+
|
87
|
+
To skip certain files or directories that Brakeman may have trouble parsing, use:
|
88
|
+
|
89
|
+
brakeman --skip-files file1,/path1/,path2/
|
90
|
+
|
91
|
+
To compare results of a scan with a previous scan, use the JSON output option and then:
|
92
|
+
|
93
|
+
brakeman --compare old_report.json
|
94
|
+
|
95
|
+
This will output JSON with two lists: one of fixed warnings and one of new warnings.
|
96
|
+
|
97
|
+
Brakeman will ignore warnings if configured to do so. By default, it looks for a configuration file in `config/brakeman.ignore`.
|
98
|
+
To create and manage this file, use:
|
99
|
+
|
100
|
+
brakeman -I
|
101
|
+
|
102
|
+
# Warning information
|
103
|
+
|
104
|
+
See [WARNING\_TYPES](WARNING_TYPES) for more information on the warnings reported by this tool.
|
105
|
+
|
106
|
+
# Warning context
|
107
|
+
|
108
|
+
The HTML output format provides an excerpt from the original application source where a warning was triggered. Due to the processing done while looking for vulnerabilities, the source may not resemble the reported warning and reported line numbers may be slightly off. However, the context still provides a quick look into the code which raised the warning.
|
109
|
+
|
110
|
+
# Confidence levels
|
111
|
+
|
112
|
+
Brakeman assigns a confidence level to each warning. This provides a rough estimate of how certain the tool is that a given warning is actually a problem. Naturally, these ratings should not be taken as absolute truth.
|
113
|
+
|
114
|
+
There are three levels of confidence:
|
115
|
+
|
116
|
+
+ High - Either this is a simple warning (boolean value) or user input is very likely being used in unsafe ways.
|
117
|
+
+ Medium - This generally indicates an unsafe use of a variable, but the variable may or may not be user input.
|
118
|
+
+ Weak - Typically means user input was indirectly used in a potentially unsafe manner.
|
119
|
+
|
120
|
+
To only get warnings above a given confidence level:
|
121
|
+
|
122
|
+
brakeman -w3
|
123
|
+
|
124
|
+
The `-w` switch takes a number from 1 to 3, with 1 being low (all warnings) and 3 being high (only highest confidence warnings).
|
125
|
+
|
126
|
+
# Configuration files
|
127
|
+
|
128
|
+
Brakeman options can stored and read from YAML files. To simplify the process of writing a configuration file, the `-C` option will output the currently set options.
|
129
|
+
|
130
|
+
Options passed in on the commandline have priority over configuration files.
|
131
|
+
|
132
|
+
The default config locations are `./config/brakeman.yml`, `~/.brakeman/config.yml`, and `/etc/brakeman/config.yml`
|
133
|
+
|
134
|
+
The `-c` option can be used to specify a configuration file to use.
|
135
|
+
|
136
|
+
# Continuous Integration
|
137
|
+
|
138
|
+
There is a [plugin available](http://brakemanscanner.org/docs/jenkins/) for Jenkins/Hudson.
|
139
|
+
|
140
|
+
For even more continuous testing, try the [Guard plugin](https://github.com/guard/guard-brakeman).
|
141
|
+
|
142
|
+
# Building
|
143
|
+
|
144
|
+
git clone git://github.com/presidentbeef/brakeman.git
|
145
|
+
cd brakeman
|
146
|
+
gem build brakeman.gemspec
|
147
|
+
gem install brakeman*.gem
|
148
|
+
|
149
|
+
# Who is Using Brakeman?
|
150
|
+
|
151
|
+
* [Code Climate](https://codeclimate.com/)
|
152
|
+
* [GitHub](https://github.com/)
|
153
|
+
* [Groupon](http://www.groupon.com/)
|
154
|
+
* [New Relic](http://newrelic.com)
|
155
|
+
* [Twitter](https://twitter.com/)
|
156
|
+
|
157
|
+
[..and more!](http://brakemanscanner.org/brakeman_users)
|
158
|
+
|
159
|
+
# Homepage/News
|
160
|
+
|
161
|
+
Website: http://brakemanscanner.org/
|
162
|
+
|
163
|
+
Twitter: https://twitter.com/brakeman
|
164
|
+
|
165
|
+
Chat: https://gitter.im/presidentbeef/brakeman
|
166
|
+
|
167
|
+
# License
|
168
|
+
|
169
|
+
see [MIT-LICENSE](MIT-LICENSE)
|
data/WARNING_TYPES
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
This file describes the various warning types reported by this tool.
|
2
|
+
|
3
|
+
# Attribute Restriction
|
4
|
+
|
5
|
+
This warning comes up if a model does not limit what attributes can be set through mass assignment.
|
6
|
+
|
7
|
+
In particular, this check looks for `attr_accessible` inside model definitions. If it is not found, this warning will be issued.
|
8
|
+
|
9
|
+
Note that disabling mass assignment globally will suppress these warnings.
|
10
|
+
|
11
|
+
# Authentication
|
12
|
+
|
13
|
+
# Basic Auth
|
14
|
+
|
15
|
+
# Command Injection
|
16
|
+
|
17
|
+
Request parameters or string interpolation has been detected in a `system` call. This can lead to someone executing arbitrary commands. Use the safe form of `system` instead, which will pass in arguments safely.
|
18
|
+
|
19
|
+
See http://guides.rubyonrails.org/security.html#command-line-injection for details.
|
20
|
+
|
21
|
+
# Cross Site Scripting
|
22
|
+
|
23
|
+
Cross site scripting warnings are raised when a parameter or model attribute is output through a view without being escaped.
|
24
|
+
|
25
|
+
See http://guides.rubyonrails.org/security.html#cross-site-scripting-xss for details.
|
26
|
+
|
27
|
+
# Cross-Site Request Forgery
|
28
|
+
|
29
|
+
No call to `protect_from_forgery` was found in `ApplicationController`. This method prevents CSRF.
|
30
|
+
|
31
|
+
See http://guides.rubyonrails.org/security.html#cross-site-request-forgery-csrf for details.
|
32
|
+
|
33
|
+
# Dangerous Eval
|
34
|
+
|
35
|
+
# Dangerous Send
|
36
|
+
|
37
|
+
# Default Routes
|
38
|
+
|
39
|
+
The general default routes warning means there is a call to `map.connect ":controller/:action/:id"` in config/routes.rb. This allows any public method on any controller to be called as an action.
|
40
|
+
|
41
|
+
If this warning is reported for a particular controller, it means there is a route to that controller containing `:action`.
|
42
|
+
|
43
|
+
Default routes can be dangerous if methods are made public which are not intended to be used as URLs or actions.
|
44
|
+
|
45
|
+
# Denial of Service
|
46
|
+
|
47
|
+
# Dynamic Render Path
|
48
|
+
|
49
|
+
When a call to `render` uses a dynamically generated path, template name, file name, or action, there is the possibility that a user can access templates that should be restricted. The issue may be worse if those templates execute code or modify the database.
|
50
|
+
|
51
|
+
This warning is shown whenever the path to be rendered is not a static string or symbol.
|
52
|
+
|
53
|
+
# File Access
|
54
|
+
|
55
|
+
# Format Validation
|
56
|
+
|
57
|
+
Calls to `validates_format_of ..., :with => //` which do not use `\A` and `\z` as anchors will cause this warning. Using `^` and `$` is not sufficient, as `$` will only match up to a new line. This allows an attacker to put whatever malicious input they would like after a new line character.
|
58
|
+
|
59
|
+
See http://guides.rubyonrails.org/security.html#regular-expressions for details.
|
60
|
+
|
61
|
+
# Information Disclosure
|
62
|
+
|
63
|
+
# Mail Link
|
64
|
+
|
65
|
+
# Mass Assignment
|
66
|
+
|
67
|
+
Mass assignment is a method for initializing models. If the attributes which are set is not restricted, someone may set the attributes to any value they wish.
|
68
|
+
|
69
|
+
Mass assignment can be disabled globally.
|
70
|
+
|
71
|
+
Please see http://railspikes.com/2008/9/22/is-your-rails-application-safe-from-mass-assignment for more details.
|
72
|
+
|
73
|
+
# Nested Attributes
|
74
|
+
|
75
|
+
# Redirect
|
76
|
+
|
77
|
+
Redirects which rely on user-supplied values can be used to "spoof" websites or hide malicious links in otherwise harmless-looking URLs. They can also allow access to restricted areas of a site if the destination is not validated.
|
78
|
+
|
79
|
+
This warning is shown when request parameters are used inside a call to `redirect_to`.
|
80
|
+
|
81
|
+
See http://www.owasp.org/index.php/Top_10_2010-A10 for more information.
|
82
|
+
|
83
|
+
# Remote Code Execution
|
84
|
+
|
85
|
+
# Response Splitting
|
86
|
+
|
87
|
+
# Session Setting
|
88
|
+
|
89
|
+
# SQL Injection
|
90
|
+
|
91
|
+
String interpolation or concatenation has been detected in an SQL query. Use parameterized queries instead.
|
92
|
+
|
93
|
+
See http://guides.rubyonrails.org/security.html#sql-injection for details.
|
94
|
+
|
95
|
+
# SSL Verification Bypass
|
data/bin/brakeman
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#Adjust path in case called directly and not through gem
|
3
|
+
$:.unshift "#{File.expand_path(File.dirname(__FILE__))}/../lib"
|
4
|
+
|
5
|
+
require 'brakeman'
|
6
|
+
require 'brakeman/options'
|
7
|
+
require 'brakeman/version'
|
8
|
+
|
9
|
+
#Parse options
|
10
|
+
begin
|
11
|
+
options, parser = Brakeman::Options.parse! ARGV
|
12
|
+
rescue OptionParser::ParseError => e
|
13
|
+
$stderr.puts e.message.capitalize
|
14
|
+
$stderr.puts "Please see `brakeman --help` for valid options"
|
15
|
+
exit(-1)
|
16
|
+
end
|
17
|
+
|
18
|
+
#Exit early for these options
|
19
|
+
if options[:list_checks] or options[:list_optional_checks]
|
20
|
+
Brakeman.list_checks options
|
21
|
+
exit
|
22
|
+
elsif options[:create_config]
|
23
|
+
Brakeman.dump_config options
|
24
|
+
exit
|
25
|
+
elsif options[:show_help]
|
26
|
+
puts parser
|
27
|
+
exit
|
28
|
+
elsif options[:show_version]
|
29
|
+
puts "brakeman #{Brakeman::Version}"
|
30
|
+
exit
|
31
|
+
elsif options[:install_rake_task]
|
32
|
+
Brakeman.install_rake_task
|
33
|
+
exit
|
34
|
+
end
|
35
|
+
|
36
|
+
#Set application path according to the commandline arguments
|
37
|
+
unless options[:app_path]
|
38
|
+
if ARGV[-1].nil?
|
39
|
+
options[:app_path] = "."
|
40
|
+
else
|
41
|
+
options[:app_path] = ARGV[-1]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
trap("INT") do
|
46
|
+
$stderr.puts "\nInterrupted - exiting."
|
47
|
+
|
48
|
+
if options[:debug]
|
49
|
+
$stderr.puts caller
|
50
|
+
end
|
51
|
+
|
52
|
+
exit!
|
53
|
+
end
|
54
|
+
|
55
|
+
if options[:quiet].nil?
|
56
|
+
options[:quiet] = :command_line
|
57
|
+
end
|
58
|
+
|
59
|
+
begin
|
60
|
+
if options[:previous_results_json]
|
61
|
+
require 'json'
|
62
|
+
vulns = Brakeman.compare options.merge(:quiet => options[:quiet])
|
63
|
+
|
64
|
+
if options[:comparison_output_file]
|
65
|
+
File.open options[:comparison_output_file], "w" do |f|
|
66
|
+
f.puts JSON.pretty_generate(vulns)
|
67
|
+
end
|
68
|
+
|
69
|
+
Brakeman.notify "Comparison saved in '#{options[:comparison_output_file]}'"
|
70
|
+
else
|
71
|
+
puts JSON.pretty_generate(vulns)
|
72
|
+
end
|
73
|
+
|
74
|
+
if options[:exit_on_warn] && vulns[:new].count > 0
|
75
|
+
exit Brakeman::Warnings_Found_Exit_Code
|
76
|
+
end
|
77
|
+
else
|
78
|
+
#Run scan and output a report
|
79
|
+
tracker = Brakeman.run options.merge(:print_report => true, :quiet => options[:quiet])
|
80
|
+
|
81
|
+
#Return error code if --exit-on-warn is used and warnings were found
|
82
|
+
if tracker.options[:exit_on_warn] and not tracker.filtered_warnings.empty?
|
83
|
+
exit Brakeman::Warnings_Found_Exit_Code
|
84
|
+
end
|
85
|
+
end
|
86
|
+
rescue Brakeman::NoApplication => e
|
87
|
+
$stderr.puts e.message
|
88
|
+
exit Brakeman::No_App_Found_Exit_Code
|
89
|
+
end
|
data/lib/brakeman.rb
ADDED
@@ -0,0 +1,495 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Brakeman
|
4
|
+
|
5
|
+
#This exit code is used when warnings are found and the --exit-on-warn
|
6
|
+
#option is set
|
7
|
+
Warnings_Found_Exit_Code = 3
|
8
|
+
|
9
|
+
#Exit code returned when no Rails application is detected
|
10
|
+
No_App_Found_Exit_Code = 4
|
11
|
+
|
12
|
+
@debug = false
|
13
|
+
@quiet = false
|
14
|
+
@loaded_dependencies = []
|
15
|
+
@vendored_paths = false
|
16
|
+
|
17
|
+
#Run Brakeman scan. Returns Tracker object.
|
18
|
+
#
|
19
|
+
#Options:
|
20
|
+
#
|
21
|
+
# * :app_path - path to root of Rails app (required)
|
22
|
+
# * :additional_checks_path - array of additional directories containing additional out-of-tree checks to run
|
23
|
+
# * :additional_libs_path - array of additional application relative lib directories (ex. app/mailers) to process
|
24
|
+
# * :assume_all_routes - assume all methods are routes (default: true)
|
25
|
+
# * :check_arguments - check arguments of methods (default: true)
|
26
|
+
# * :collapse_mass_assignment - report unprotected models in single warning (default: false)
|
27
|
+
# * :combine_locations - combine warning locations (default: true)
|
28
|
+
# * :config_file - configuration file
|
29
|
+
# * :escape_html - escape HTML by default (automatic)
|
30
|
+
# * :exit_on_warn - return false if warnings found, true otherwise. Not recommended for library use (default: false)
|
31
|
+
# * :github_repo - github repo to use for file links (user/repo[/path][@ref])
|
32
|
+
# * :highlight_user_input - highlight user input in reported warnings (default: true)
|
33
|
+
# * :html_style - path to CSS file
|
34
|
+
# * :ignore_model_output - consider models safe (default: false)
|
35
|
+
# * :index_libs - add libraries to call index (default: true)
|
36
|
+
# * :interprocedural - limited interprocedural processing of method calls (default: false)
|
37
|
+
# * :message_limit - limit length of messages
|
38
|
+
# * :min_confidence - minimum confidence (0-2, 0 is highest)
|
39
|
+
# * :output_files - files for output
|
40
|
+
# * :output_formats - formats for output (:to_s, :to_tabs, :to_csv, :to_html)
|
41
|
+
# * :parallel_checks - run checks in parallel (default: true)
|
42
|
+
# * :print_report - if no output file specified, print to stdout (default: false)
|
43
|
+
# * :quiet - suppress most messages (default: true)
|
44
|
+
# * :rails3 - force Rails 3 mode (automatic)
|
45
|
+
# * :report_routes - show found routes on controllers (default: false)
|
46
|
+
# * :run_checks - array of checks to run (run all if not specified)
|
47
|
+
# * :safe_methods - array of methods to consider safe
|
48
|
+
# * :skip_libs - do not process lib/ directory (default: false)
|
49
|
+
# * :skip_checks - checks not to run (run all if not specified)
|
50
|
+
# * :absolute_paths - show absolute path of each file (default: false)
|
51
|
+
# * :summary_only - only output summary section of report
|
52
|
+
# (does not apply to tabs format)
|
53
|
+
#
|
54
|
+
#Alternatively, just supply a path as a string.
|
55
|
+
def self.run options
|
56
|
+
options = set_options options
|
57
|
+
|
58
|
+
@quiet = !!options[:quiet]
|
59
|
+
@debug = !!options[:debug]
|
60
|
+
|
61
|
+
if @quiet
|
62
|
+
options[:report_progress] = false
|
63
|
+
end
|
64
|
+
scan options
|
65
|
+
end
|
66
|
+
|
67
|
+
#Sets up options for run, checks given application path
|
68
|
+
def self.set_options options
|
69
|
+
if options.is_a? String
|
70
|
+
options = { :app_path => options }
|
71
|
+
end
|
72
|
+
|
73
|
+
if options[:quiet] == :command_line
|
74
|
+
command_line = true
|
75
|
+
options.delete :quiet
|
76
|
+
end
|
77
|
+
|
78
|
+
options = default_options.merge(load_options(options)).merge(options)
|
79
|
+
|
80
|
+
if options[:quiet].nil? and not command_line
|
81
|
+
options[:quiet] = true
|
82
|
+
end
|
83
|
+
|
84
|
+
options[:output_formats] = get_output_formats options
|
85
|
+
options[:github_url] = get_github_url options
|
86
|
+
|
87
|
+
options
|
88
|
+
end
|
89
|
+
|
90
|
+
#Load options from YAML file
|
91
|
+
def self.load_options line_options
|
92
|
+
custom_location = line_options[:config_file]
|
93
|
+
quiet = line_options[:quiet]
|
94
|
+
app_path = line_options[:app_path]
|
95
|
+
|
96
|
+
#Load configuration file
|
97
|
+
if config = config_file(custom_location, app_path)
|
98
|
+
require 'date' # https://github.com/dtao/safe_yaml/issues/80
|
99
|
+
self.load_brakeman_dependency 'safe_yaml/load'
|
100
|
+
options = SafeYAML.load_file config, :deserialize_symbols => true
|
101
|
+
|
102
|
+
if options
|
103
|
+
options.each { |k, v| options[k] = Set.new v if v.is_a? Array }
|
104
|
+
|
105
|
+
# After parsing the yaml config file for options, convert any string keys into symbols.
|
106
|
+
options.keys.select {|k| k.is_a? String}.map {|k| k.to_sym }.each {|k| options[k] = options[k.to_s]; options.delete(k.to_s) }
|
107
|
+
|
108
|
+
# notify if options[:quiet] and quiet is nil||false
|
109
|
+
notify "[Notice] Using configuration in #{config}" unless (options[:quiet] || quiet)
|
110
|
+
options
|
111
|
+
else
|
112
|
+
notify "[Notice] Empty configuration file: #{config}" unless quiet
|
113
|
+
{}
|
114
|
+
end
|
115
|
+
else
|
116
|
+
{}
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
CONFIG_FILES = [
|
121
|
+
File.expand_path("~/.brakeman/config.yml"),
|
122
|
+
File.expand_path("/etc/brakeman/config.yml")
|
123
|
+
]
|
124
|
+
|
125
|
+
def self.config_file custom_location, app_path
|
126
|
+
app_config = File.expand_path(File.join(app_path, "config", "brakeman.yml"))
|
127
|
+
supported_locations = [File.expand_path(custom_location || ""), app_config] + CONFIG_FILES
|
128
|
+
supported_locations.detect {|f| File.file?(f) }
|
129
|
+
end
|
130
|
+
|
131
|
+
#Default set of options
|
132
|
+
def self.default_options
|
133
|
+
{ :assume_all_routes => true,
|
134
|
+
:skip_checks => Set.new,
|
135
|
+
:check_arguments => true,
|
136
|
+
:safe_methods => Set.new,
|
137
|
+
:min_confidence => 2,
|
138
|
+
:combine_locations => true,
|
139
|
+
:collapse_mass_assignment => false,
|
140
|
+
:highlight_user_input => true,
|
141
|
+
:ignore_redirect_to_model => true,
|
142
|
+
:ignore_model_output => false,
|
143
|
+
:index_libs => true,
|
144
|
+
:message_limit => 100,
|
145
|
+
:parallel_checks => true,
|
146
|
+
:relative_path => false,
|
147
|
+
:report_progress => true,
|
148
|
+
:html_style => "#{File.expand_path(File.dirname(__FILE__))}/brakeman/format/style.css"
|
149
|
+
}
|
150
|
+
end
|
151
|
+
|
152
|
+
#Determine output formats based on options[:output_formats]
|
153
|
+
#or options[:output_files]
|
154
|
+
def self.get_output_formats options
|
155
|
+
#Set output format
|
156
|
+
if options[:output_format] && options[:output_files] && options[:output_files].size > 1
|
157
|
+
raise ArgumentError, "Cannot specify output format if multiple output files specified"
|
158
|
+
end
|
159
|
+
if options[:output_format]
|
160
|
+
get_formats_from_output_format options[:output_format]
|
161
|
+
elsif options[:output_files]
|
162
|
+
get_formats_from_output_files options[:output_files]
|
163
|
+
else
|
164
|
+
begin
|
165
|
+
self.load_brakeman_dependency 'terminal-table', :allow_fail
|
166
|
+
return [:to_s]
|
167
|
+
rescue LoadError
|
168
|
+
return [:to_json]
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def self.get_formats_from_output_format output_format
|
174
|
+
case output_format
|
175
|
+
when :html, :to_html
|
176
|
+
[:to_html]
|
177
|
+
when :csv, :to_csv
|
178
|
+
[:to_csv]
|
179
|
+
when :pdf, :to_pdf
|
180
|
+
[:to_pdf]
|
181
|
+
when :tabs, :to_tabs
|
182
|
+
[:to_tabs]
|
183
|
+
when :json, :to_json
|
184
|
+
[:to_json]
|
185
|
+
when :markdown, :to_markdown
|
186
|
+
[:to_markdown]
|
187
|
+
when :cc, :to_cc, :codeclimate, :to_codeclimate
|
188
|
+
[:to_codeclimate]
|
189
|
+
else
|
190
|
+
[:to_s]
|
191
|
+
end
|
192
|
+
end
|
193
|
+
private_class_method :get_formats_from_output_format
|
194
|
+
|
195
|
+
def self.get_formats_from_output_files output_files
|
196
|
+
output_files.map do |output_file|
|
197
|
+
case output_file
|
198
|
+
when /\.html$/i
|
199
|
+
:to_html
|
200
|
+
when /\.csv$/i
|
201
|
+
:to_csv
|
202
|
+
when /\.pdf$/i
|
203
|
+
:to_pdf
|
204
|
+
when /\.tabs$/i
|
205
|
+
:to_tabs
|
206
|
+
when /\.json$/i
|
207
|
+
:to_json
|
208
|
+
when /\.md$/i
|
209
|
+
:to_markdown
|
210
|
+
when /(\.cc|\.codeclimate)$/i
|
211
|
+
:to_codeclimate
|
212
|
+
else
|
213
|
+
:to_s
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
private_class_method :get_formats_from_output_files
|
218
|
+
|
219
|
+
def self.get_github_url options
|
220
|
+
if github_repo = options[:github_repo]
|
221
|
+
full_repo, ref = github_repo.split '@', 2
|
222
|
+
name, repo, path = full_repo.split '/', 3
|
223
|
+
unless name && repo && !(name.empty? || repo.empty?)
|
224
|
+
raise ArgumentError, "Invalid GitHub repository format"
|
225
|
+
end
|
226
|
+
path.chomp '/' if path
|
227
|
+
ref ||= 'master'
|
228
|
+
['https://github.com', name, repo, 'blob', ref, path].compact.join '/'
|
229
|
+
else
|
230
|
+
nil
|
231
|
+
end
|
232
|
+
end
|
233
|
+
private_class_method :get_github_url
|
234
|
+
|
235
|
+
#Output list of checks (for `-k` option)
|
236
|
+
def self.list_checks options
|
237
|
+
require 'brakeman/scanner'
|
238
|
+
|
239
|
+
add_external_checks options
|
240
|
+
|
241
|
+
if options[:list_optional_checks]
|
242
|
+
$stderr.puts "Optional Checks:"
|
243
|
+
checks = Checks.optional_checks
|
244
|
+
else
|
245
|
+
$stderr.puts "Available Checks:"
|
246
|
+
checks = Checks.checks
|
247
|
+
end
|
248
|
+
|
249
|
+
format_length = 30
|
250
|
+
|
251
|
+
$stderr.puts "-" * format_length
|
252
|
+
checks.each do |check|
|
253
|
+
$stderr.printf("%-#{format_length}s%s\n", check.name, check.description)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
#Installs Rake task for running Brakeman,
|
258
|
+
#which basically means copying `lib/brakeman/brakeman.rake` to
|
259
|
+
#`lib/tasks/brakeman.rake` in the current Rails application.
|
260
|
+
def self.install_rake_task install_path = nil
|
261
|
+
if install_path
|
262
|
+
rake_path = File.join(install_path, "Rakefile")
|
263
|
+
task_path = File.join(install_path, "lib", "tasks", "brakeman.rake")
|
264
|
+
else
|
265
|
+
rake_path = "Rakefile"
|
266
|
+
task_path = File.join("lib", "tasks", "brakeman.rake")
|
267
|
+
end
|
268
|
+
|
269
|
+
if not File.exist? rake_path
|
270
|
+
raise RakeInstallError, "No Rakefile detected"
|
271
|
+
elsif File.exist? task_path
|
272
|
+
raise RakeInstallError, "Task already exists"
|
273
|
+
end
|
274
|
+
|
275
|
+
require 'fileutils'
|
276
|
+
|
277
|
+
if not File.exist? "lib/tasks"
|
278
|
+
notify "Creating lib/tasks"
|
279
|
+
FileUtils.mkdir_p "lib/tasks"
|
280
|
+
end
|
281
|
+
|
282
|
+
path = File.expand_path(File.dirname(__FILE__))
|
283
|
+
|
284
|
+
FileUtils.cp "#{path}/brakeman/brakeman.rake", task_path
|
285
|
+
|
286
|
+
if File.exist? task_path
|
287
|
+
notify "Task created in #{task_path}"
|
288
|
+
notify "Usage: rake brakeman:run[output_file]"
|
289
|
+
else
|
290
|
+
raise RakeInstallError, "Could not create task"
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
#Output configuration to YAML
|
295
|
+
def self.dump_config options
|
296
|
+
require 'yaml'
|
297
|
+
if options[:create_config].is_a? String
|
298
|
+
file = options[:create_config]
|
299
|
+
else
|
300
|
+
file = nil
|
301
|
+
end
|
302
|
+
|
303
|
+
options.delete :create_config
|
304
|
+
|
305
|
+
options.each do |k,v|
|
306
|
+
if v.is_a? Set
|
307
|
+
options[k] = v.to_a
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
if file
|
312
|
+
File.open file, "w" do |f|
|
313
|
+
YAML.dump options, f
|
314
|
+
end
|
315
|
+
notify "Output configuration to #{file}"
|
316
|
+
else
|
317
|
+
notify YAML.dump(options)
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
#Run a scan. Generally called from Brakeman.run instead of directly.
|
322
|
+
def self.scan options
|
323
|
+
#Load scanner
|
324
|
+
notify "Loading scanner..."
|
325
|
+
|
326
|
+
begin
|
327
|
+
require 'brakeman/scanner'
|
328
|
+
rescue LoadError
|
329
|
+
raise NoBrakemanError, "Cannot find lib/ directory."
|
330
|
+
end
|
331
|
+
|
332
|
+
add_external_checks options
|
333
|
+
|
334
|
+
#Start scanning
|
335
|
+
scanner = Scanner.new options
|
336
|
+
tracker = scanner.tracker
|
337
|
+
|
338
|
+
notify "Processing application in #{tracker.app_path}"
|
339
|
+
scanner.process
|
340
|
+
|
341
|
+
if options[:parallel_checks]
|
342
|
+
notify "Running checks in parallel..."
|
343
|
+
else
|
344
|
+
notify "Runnning checks..."
|
345
|
+
end
|
346
|
+
|
347
|
+
tracker.run_checks
|
348
|
+
|
349
|
+
self.filter_warnings tracker, options
|
350
|
+
|
351
|
+
if options[:output_files]
|
352
|
+
notify "Generating report..."
|
353
|
+
|
354
|
+
write_report_to_files tracker, options[:output_files]
|
355
|
+
elsif options[:print_report]
|
356
|
+
notify "Generating report..."
|
357
|
+
|
358
|
+
write_report_to_formats tracker, options[:output_formats]
|
359
|
+
end
|
360
|
+
|
361
|
+
tracker
|
362
|
+
end
|
363
|
+
|
364
|
+
def self.write_report_to_files tracker, output_files
|
365
|
+
output_files.each_with_index do |output_file, idx|
|
366
|
+
File.open output_file, "w" do |f|
|
367
|
+
f.write tracker.report.format(tracker.options[:output_formats][idx])
|
368
|
+
end
|
369
|
+
notify "Report saved in '#{output_file}'"
|
370
|
+
end
|
371
|
+
end
|
372
|
+
private_class_method :write_report_to_files
|
373
|
+
|
374
|
+
def self.write_report_to_formats tracker, output_formats
|
375
|
+
output_formats.each do |output_format|
|
376
|
+
puts tracker.report.format(output_format)
|
377
|
+
end
|
378
|
+
end
|
379
|
+
private_class_method :write_report_to_formats
|
380
|
+
|
381
|
+
#Rescan a subset of files in a Rails application.
|
382
|
+
#
|
383
|
+
#A full scan must have been run already to use this method.
|
384
|
+
#The returned Tracker object from Brakeman.run is used as a starting point
|
385
|
+
#for the rescan.
|
386
|
+
#
|
387
|
+
#Options may be given as a hash with the same values as Brakeman.run.
|
388
|
+
#Note that these options will be merged into the Tracker.
|
389
|
+
#
|
390
|
+
#This method returns a RescanReport object with information about the scan.
|
391
|
+
#However, the Tracker object will also be modified as the scan is run.
|
392
|
+
def self.rescan tracker, files, options = {}
|
393
|
+
require 'brakeman/rescanner'
|
394
|
+
|
395
|
+
tracker.options.merge! options
|
396
|
+
|
397
|
+
@quiet = !!tracker.options[:quiet]
|
398
|
+
@debug = !!tracker.options[:debug]
|
399
|
+
|
400
|
+
Rescanner.new(tracker.options, tracker.processor, files).recheck
|
401
|
+
end
|
402
|
+
|
403
|
+
def self.notify message
|
404
|
+
$stderr.puts message unless @quiet
|
405
|
+
end
|
406
|
+
|
407
|
+
def self.debug message
|
408
|
+
$stderr.puts message if @debug
|
409
|
+
end
|
410
|
+
|
411
|
+
# Compare JSON ouptut from a previous scan and return the diff of the two scans
|
412
|
+
def self.compare options
|
413
|
+
require 'json'
|
414
|
+
require 'brakeman/differ'
|
415
|
+
raise ArgumentError.new("Comparison file doesn't exist") unless File.exist? options[:previous_results_json]
|
416
|
+
|
417
|
+
begin
|
418
|
+
previous_results = JSON.parse(File.read(options[:previous_results_json]), :symbolize_names => true)[:warnings]
|
419
|
+
rescue JSON::ParserError
|
420
|
+
self.notify "Error parsing comparison file: #{options[:previous_results_json]}"
|
421
|
+
exit!
|
422
|
+
end
|
423
|
+
|
424
|
+
tracker = run(options)
|
425
|
+
|
426
|
+
new_results = JSON.parse(tracker.report.to_json, :symbolize_names => true)[:warnings]
|
427
|
+
|
428
|
+
Brakeman::Differ.new(new_results, previous_results).diff
|
429
|
+
end
|
430
|
+
|
431
|
+
def self.load_brakeman_dependency name, allow_fail = false
|
432
|
+
return if @loaded_dependencies.include? name
|
433
|
+
|
434
|
+
unless @vendored_paths
|
435
|
+
path_load = "#{File.expand_path(File.dirname(__FILE__))}/../bundle/load.rb"
|
436
|
+
|
437
|
+
if File.exist? path_load
|
438
|
+
require path_load
|
439
|
+
end
|
440
|
+
|
441
|
+
@vendored_paths = true
|
442
|
+
end
|
443
|
+
|
444
|
+
begin
|
445
|
+
require name
|
446
|
+
rescue LoadError => e
|
447
|
+
if allow_fail
|
448
|
+
raise e
|
449
|
+
else
|
450
|
+
$stderr.puts e.message
|
451
|
+
$stderr.puts "Please install the appropriate dependency: #{name}."
|
452
|
+
exit!(-1)
|
453
|
+
end
|
454
|
+
end
|
455
|
+
end
|
456
|
+
|
457
|
+
def self.filter_warnings tracker, options
|
458
|
+
require 'brakeman/report/ignore/config'
|
459
|
+
|
460
|
+
app_tree = Brakeman::AppTree.from_options(options)
|
461
|
+
|
462
|
+
if options[:ignore_file]
|
463
|
+
file = options[:ignore_file]
|
464
|
+
elsif app_tree.exists? "config/brakeman.ignore"
|
465
|
+
file = app_tree.expand_path("config/brakeman.ignore")
|
466
|
+
elsif not options[:interactive_ignore]
|
467
|
+
return
|
468
|
+
end
|
469
|
+
|
470
|
+
notify "Filtering warnings..."
|
471
|
+
|
472
|
+
if options[:interactive_ignore]
|
473
|
+
require 'brakeman/report/ignore/interactive'
|
474
|
+
config = InteractiveIgnorer.new(file, tracker.warnings).start
|
475
|
+
else
|
476
|
+
notify "[Notice] Using '#{file}' to filter warnings"
|
477
|
+
config = IgnoreConfig.new(file, tracker.warnings)
|
478
|
+
config.read_from_file
|
479
|
+
config.filter_ignored
|
480
|
+
end
|
481
|
+
|
482
|
+
tracker.ignored_filter = config
|
483
|
+
end
|
484
|
+
|
485
|
+
def self.add_external_checks options
|
486
|
+
options[:additional_checks_path].each do |path|
|
487
|
+
Brakeman::Checks.initialize_checks path
|
488
|
+
end if options[:additional_checks_path]
|
489
|
+
end
|
490
|
+
|
491
|
+
class DependencyError < RuntimeError; end
|
492
|
+
class RakeInstallError < RuntimeError; end
|
493
|
+
class NoBrakemanError < RuntimeError; end
|
494
|
+
class NoApplication < RuntimeError; end
|
495
|
+
end
|