brakeman 4.10.0 → 5.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (197) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +46 -0
  3. data/README.md +11 -2
  4. data/bundle/load.rb +5 -3
  5. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/CHANGELOG.md +16 -0
  6. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/FAQ.md +0 -0
  7. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/Gemfile +1 -4
  8. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/MIT-LICENSE +0 -0
  9. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/README.md +2 -3
  10. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/REFERENCE.md +29 -7
  11. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/TODO +0 -0
  12. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/haml.gemspec +2 -1
  13. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml.rb +0 -0
  14. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/attribute_builder.rb +3 -3
  15. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/attribute_compiler.rb +42 -31
  16. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/attribute_parser.rb +0 -0
  17. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/buffer.rb +0 -0
  18. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/compiler.rb +0 -0
  19. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/engine.rb +0 -0
  20. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/error.rb +0 -0
  21. data/bundle/ruby/2.7.0/gems/haml-5.2.1/lib/haml/escapable.rb +77 -0
  22. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/exec.rb +0 -0
  23. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/filters.rb +0 -0
  24. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/generator.rb +0 -0
  25. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/helpers.rb +7 -1
  26. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/helpers/action_view_extensions.rb +0 -0
  27. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/helpers/action_view_mods.rb +0 -0
  28. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/helpers/action_view_xss_mods.rb +0 -0
  29. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/helpers/safe_erubi_template.rb +0 -0
  30. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/helpers/safe_erubis_template.rb +0 -0
  31. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/helpers/xss_mods.rb +6 -3
  32. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/options.rb +0 -0
  33. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/parser.rb +32 -4
  34. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/plugin.rb +0 -0
  35. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/railtie.rb +0 -0
  36. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/sass_rails_filter.rb +0 -0
  37. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/template.rb +0 -0
  38. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/template/options.rb +0 -0
  39. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/temple_engine.rb +0 -0
  40. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/temple_line_counter.rb +0 -0
  41. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/util.rb +1 -1
  42. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/version.rb +1 -1
  43. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/yard/default/fulldoc/html/css/common.sass +0 -0
  44. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/yard/default/layout/html/footer.erb +0 -0
  45. data/bundle/ruby/2.7.0/gems/parallel-1.20.1/MIT-LICENSE.txt +20 -0
  46. data/bundle/ruby/2.7.0/gems/parallel-1.20.1/lib/parallel.rb +523 -0
  47. data/bundle/ruby/2.7.0/gems/parallel-1.20.1/lib/parallel/processor_count.rb +42 -0
  48. data/bundle/ruby/2.7.0/gems/parallel-1.20.1/lib/parallel/version.rb +3 -0
  49. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/LICENSE.txt +22 -0
  50. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/NEWS.md +178 -0
  51. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/README.md +48 -0
  52. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml.rb +3 -0
  53. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/attlistdecl.rb +63 -0
  54. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/attribute.rb +205 -0
  55. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/cdata.rb +68 -0
  56. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/child.rb +97 -0
  57. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/comment.rb +80 -0
  58. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/doctype.rb +311 -0
  59. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/document.rb +451 -0
  60. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/dtd/attlistdecl.rb +11 -0
  61. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/dtd/dtd.rb +47 -0
  62. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/dtd/elementdecl.rb +18 -0
  63. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/dtd/entitydecl.rb +57 -0
  64. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/dtd/notationdecl.rb +40 -0
  65. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/element.rb +2599 -0
  66. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/encoding.rb +51 -0
  67. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/entity.rb +171 -0
  68. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/formatters/default.rb +116 -0
  69. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/formatters/pretty.rb +142 -0
  70. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/formatters/transitive.rb +58 -0
  71. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/functions.rb +447 -0
  72. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/instruction.rb +79 -0
  73. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/light/node.rb +188 -0
  74. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/namespace.rb +59 -0
  75. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/node.rb +76 -0
  76. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/output.rb +30 -0
  77. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/parent.rb +166 -0
  78. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/parseexception.rb +52 -0
  79. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb +694 -0
  80. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/parsers/lightparser.rb +59 -0
  81. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/parsers/pullparser.rb +197 -0
  82. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/parsers/sax2parser.rb +273 -0
  83. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/parsers/streamparser.rb +61 -0
  84. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/parsers/treeparser.rb +101 -0
  85. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/parsers/ultralightparser.rb +57 -0
  86. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/parsers/xpathparser.rb +689 -0
  87. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/quickpath.rb +266 -0
  88. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/rexml.rb +37 -0
  89. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/sax2listener.rb +98 -0
  90. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/security.rb +28 -0
  91. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/source.rb +298 -0
  92. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/streamlistener.rb +93 -0
  93. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/text.rb +424 -0
  94. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/undefinednamespaceexception.rb +9 -0
  95. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/validation/relaxng.rb +539 -0
  96. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/validation/validation.rb +144 -0
  97. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/validation/validationexception.rb +10 -0
  98. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/xmldecl.rb +130 -0
  99. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/xmltokens.rb +85 -0
  100. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/xpath.rb +81 -0
  101. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/xpath_parser.rb +974 -0
  102. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/History.rdoc +25 -0
  103. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/Manifest.txt +2 -0
  104. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/README.rdoc +0 -0
  105. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/compare/normalize.rb +2 -2
  106. data/bundle/ruby/2.7.0/gems/ruby_parser-3.16.0/debugging.md +190 -0
  107. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/lib/rp_extensions.rb +0 -0
  108. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/lib/rp_stringscanner.rb +0 -0
  109. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/lib/ruby20_parser.rb +2392 -2384
  110. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/lib/ruby20_parser.y +6 -1
  111. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/lib/ruby21_parser.rb +2553 -2550
  112. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/lib/ruby21_parser.y +6 -1
  113. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/lib/ruby22_parser.rb +2491 -2471
  114. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/lib/ruby22_parser.y +6 -1
  115. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/lib/ruby23_parser.rb +2422 -2403
  116. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/lib/ruby23_parser.y +6 -1
  117. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/lib/ruby24_parser.rb +2460 -2450
  118. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/lib/ruby24_parser.y +6 -1
  119. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/lib/ruby25_parser.rb +2450 -2441
  120. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/lib/ruby25_parser.y +6 -1
  121. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/lib/ruby26_parser.rb +2444 -2433
  122. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/lib/ruby26_parser.y +7 -1
  123. data/bundle/ruby/2.7.0/gems/ruby_parser-3.16.0/lib/ruby27_parser.rb +7310 -0
  124. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/lib/ruby27_parser.y +21 -1
  125. data/bundle/ruby/2.7.0/gems/ruby_parser-3.16.0/lib/ruby30_parser.rb +7310 -0
  126. data/bundle/ruby/2.7.0/gems/ruby_parser-3.16.0/lib/ruby30_parser.y +2677 -0
  127. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/lib/ruby_lexer.rb +19 -0
  128. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/lib/ruby_lexer.rex +1 -1
  129. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/lib/ruby_lexer.rex.rb +1 -1
  130. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/lib/ruby_parser.rb +2 -0
  131. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/lib/ruby_parser.yy +27 -1
  132. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/lib/ruby_parser_extras.rb +2 -2
  133. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/tools/munge.rb +2 -2
  134. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.16.0}/tools/ripper.rb +0 -0
  135. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.1 → sexp_processor-4.15.3}/History.rdoc +12 -0
  136. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.1 → sexp_processor-4.15.3}/Manifest.txt +0 -0
  137. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.1 → sexp_processor-4.15.3}/README.rdoc +0 -0
  138. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.1 → sexp_processor-4.15.3}/lib/composite_sexp_processor.rb +0 -0
  139. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.1 → sexp_processor-4.15.3}/lib/pt_testcase.rb +2 -2
  140. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.1 → sexp_processor-4.15.3}/lib/sexp.rb +0 -0
  141. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.1 → sexp_processor-4.15.3}/lib/sexp_matcher.rb +0 -0
  142. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.1 → sexp_processor-4.15.3}/lib/sexp_processor.rb +1 -1
  143. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.1 → sexp_processor-4.15.3}/lib/strict_sexp.rb +0 -0
  144. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.1 → sexp_processor-4.15.3}/lib/unique.rb +0 -0
  145. data/lib/brakeman.rb +21 -4
  146. data/lib/brakeman/app_tree.rb +36 -3
  147. data/lib/brakeman/checks/base_check.rb +7 -1
  148. data/lib/brakeman/checks/check_detailed_exceptions.rb +1 -1
  149. data/lib/brakeman/checks/check_evaluation.rb +1 -1
  150. data/lib/brakeman/checks/check_execute.rb +2 -1
  151. data/lib/brakeman/checks/check_mass_assignment.rb +4 -6
  152. data/lib/brakeman/checks/check_regex_dos.rb +1 -1
  153. data/lib/brakeman/checks/check_sanitize_methods.rb +2 -1
  154. data/lib/brakeman/checks/check_sql.rb +16 -3
  155. data/lib/brakeman/checks/check_unsafe_reflection_methods.rb +68 -0
  156. data/lib/brakeman/checks/check_verb_confusion.rb +75 -0
  157. data/lib/brakeman/file_parser.rb +50 -22
  158. data/lib/brakeman/options.rb +5 -1
  159. data/lib/brakeman/parsers/template_parser.rb +26 -3
  160. data/lib/brakeman/processors/alias_processor.rb +91 -19
  161. data/lib/brakeman/processors/base_processor.rb +4 -4
  162. data/lib/brakeman/processors/controller_alias_processor.rb +6 -43
  163. data/lib/brakeman/processors/controller_processor.rb +1 -1
  164. data/lib/brakeman/processors/haml_template_processor.rb +8 -1
  165. data/lib/brakeman/processors/lib/call_conversion_helper.rb +10 -0
  166. data/lib/brakeman/processors/lib/file_type_detector.rb +64 -0
  167. data/lib/brakeman/processors/lib/rails3_config_processor.rb +16 -16
  168. data/lib/brakeman/processors/lib/rails4_config_processor.rb +2 -1
  169. data/lib/brakeman/processors/library_processor.rb +9 -0
  170. data/lib/brakeman/processors/output_processor.rb +1 -1
  171. data/lib/brakeman/processors/template_alias_processor.rb +5 -0
  172. data/lib/brakeman/report.rb +12 -1
  173. data/lib/brakeman/report/ignore/interactive.rb +1 -1
  174. data/lib/brakeman/report/report_base.rb +0 -2
  175. data/lib/brakeman/report/report_csv.rb +37 -60
  176. data/lib/brakeman/report/report_github.rb +31 -0
  177. data/lib/brakeman/report/report_junit.rb +2 -2
  178. data/lib/brakeman/report/report_sarif.rb +1 -1
  179. data/lib/brakeman/report/report_sonar.rb +38 -0
  180. data/lib/brakeman/report/report_tabs.rb +1 -1
  181. data/lib/brakeman/report/report_text.rb +1 -1
  182. data/lib/brakeman/rescanner.rb +7 -5
  183. data/lib/brakeman/scanner.rb +47 -18
  184. data/lib/brakeman/tracker.rb +39 -4
  185. data/lib/brakeman/tracker/collection.rb +27 -5
  186. data/lib/brakeman/tracker/config.rb +73 -0
  187. data/lib/brakeman/tracker/controller.rb +1 -1
  188. data/lib/brakeman/tracker/method_info.rb +29 -0
  189. data/lib/brakeman/util.rb +17 -4
  190. data/lib/brakeman/version.rb +1 -1
  191. data/lib/brakeman/warning.rb +10 -2
  192. data/lib/brakeman/warning_codes.rb +2 -0
  193. data/lib/ruby_parser/bm_sexp.rb +9 -9
  194. metadata +149 -84
  195. data/bundle/ruby/2.7.0/gems/haml-5.1.2/lib/haml/escapable.rb +0 -50
  196. data/bundle/ruby/2.7.0/gems/ruby_parser-3.15.0/debugging.md +0 -57
  197. data/bundle/ruby/2.7.0/gems/ruby_parser-3.15.0/lib/ruby27_parser.rb +0 -7224
@@ -0,0 +1,31 @@
1
+ # Github Actions Formatter
2
+ # Formats warnings as workflow commands to create annotations in GitHub UI
3
+ class Brakeman::Report::Github < Brakeman::Report::Base
4
+ def generate_report
5
+ # @see https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message
6
+ errors.concat(warnings).join("\n")
7
+ end
8
+
9
+ def warnings
10
+ all_warnings
11
+ .map { |warning| "::warning file=#{warning_file(warning)},line=#{warning.line}::#{warning.message}" }
12
+ end
13
+
14
+ def errors
15
+ tracker.errors.map do |error|
16
+ if error[:exception].is_a?(Racc::ParseError)
17
+ # app/services/balance.rb:4 :: parse error on value "..." (tDOT3)
18
+ file, line = error[:exception].message.split(':').map(&:strip)[0,2]
19
+ "::error file=#{file},line=#{line}::#{clean_message(error[:error])}"
20
+ else
21
+ "::error ::#{clean_message(error[:error])}"
22
+ end
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def clean_message(msg)
29
+ msg.gsub('::','').squeeze(' ')
30
+ end
31
+ end
@@ -47,7 +47,7 @@ class Brakeman::Report::JUnit < Brakeman::Report::Base
47
47
  warning.add_attribute 'brakeman:file', warning_file(w)
48
48
  warning.add_attribute 'brakeman:line', w.line
49
49
  warning.add_attribute 'brakeman:fingerprint', w.fingerprint
50
- warning.add_attribute 'brakeman:confidence', TEXT_CONFIDENCE[w.confidence]
50
+ warning.add_attribute 'brakeman:confidence', w.confidence_name
51
51
  warning.add_attribute 'brakeman:code', w.format_code
52
52
  warning.add_text w.to_s
53
53
  }
@@ -88,7 +88,7 @@ class Brakeman::Report::JUnit < Brakeman::Report::Base
88
88
  failure.add_attribute 'brakeman:fingerprint', warning.fingerprint
89
89
  failure.add_attribute 'brakeman:file', warning_file(warning)
90
90
  failure.add_attribute 'brakeman:line', warning.line
91
- failure.add_attribute 'brakeman:confidence', TEXT_CONFIDENCE[warning.confidence]
91
+ failure.add_attribute 'brakeman:confidence', warning.confidence_name
92
92
  failure.add_attribute 'brakeman:code', warning.format_code
93
93
  failure.add_text warning.to_s
94
94
  }
@@ -27,7 +27,7 @@ class Brakeman::Report::SARIF < Brakeman::Report::Base
27
27
  def rules
28
28
  @rules ||= unique_warnings_by_warning_code.map do |warning|
29
29
  rule_id = render_id warning
30
- check_name = warning.check.gsub(/^Brakeman::Check/, '')
30
+ check_name = warning.check_name
31
31
  check_description = render_message check_descriptions[check_name]
32
32
  {
33
33
  :id => rule_id,
@@ -0,0 +1,38 @@
1
+ class Brakeman::Report::Sonar < Brakeman::Report::Base
2
+ def generate_report
3
+ report_object = {
4
+ issues: all_warnings.map { |warning| issue_json(warning) }
5
+ }
6
+ return JSON.pretty_generate report_object
7
+ end
8
+
9
+ private
10
+
11
+ def issue_json(warning)
12
+ {
13
+ engineId: "Brakeman",
14
+ ruleId: warning.warning_code,
15
+ type: "VULNERABILITY",
16
+ severity: severity_level_for(warning.confidence),
17
+ primaryLocation: {
18
+ message: warning.message,
19
+ filePath: warning.file.relative,
20
+ textRange: {
21
+ "startLine": warning.line || 1,
22
+ "endLine": warning.line || 1,
23
+ }
24
+ },
25
+ effortMinutes: (4 - warning.confidence) * 15
26
+ }
27
+ end
28
+
29
+ def severity_level_for(confidence)
30
+ if confidence == 0
31
+ "CRITICAL"
32
+ elsif confidence == 1
33
+ "MAJOR"
34
+ else
35
+ "MINOR"
36
+ end
37
+ end
38
+ end
@@ -10,7 +10,7 @@ class Brakeman::Report::Tabs < Brakeman::Report::Table
10
10
  self.send(meth).map do |w|
11
11
  line = w.line || 0
12
12
  w.warning_type.gsub!(/[^\w\s]/, ' ')
13
- "#{(w.file.absolute)}\t#{line}\t#{w.warning_type}\t#{category}\t#{w.format_message}\t#{TEXT_CONFIDENCE[w.confidence]}"
13
+ "#{(w.file.absolute)}\t#{line}\t#{w.warning_type}\t#{category}\t#{w.format_message}\t#{w.confidence_name}"
14
14
  end.join "\n"
15
15
 
16
16
  end.join "\n"
@@ -160,7 +160,7 @@ class Brakeman::Report::Text < Brakeman::Report::Base
160
160
  when :category
161
161
  label('Category', w.warning_type.to_s)
162
162
  when :check
163
- label('Check', w.check.gsub(/^Brakeman::Check/, ''))
163
+ label('Check', w.check_name)
164
164
  when :message
165
165
  label('Message', w.message)
166
166
  when :code
@@ -132,10 +132,11 @@ class Brakeman::Rescanner < Brakeman::Scanner
132
132
  template_name = template_path_to_name(path)
133
133
 
134
134
  tracker.reset_template template_name
135
- fp = Brakeman::FileParser.new(tracker)
135
+ fp = Brakeman::FileParser.new(tracker.app_tree, tracker.options[:parser_timeout])
136
136
  template_parser = Brakeman::TemplateParser.new(tracker, fp)
137
137
  template_parser.parse_template path, path.read
138
- process_template fp.file_list[:templates].first
138
+ tracker.add_errors(fp.errors)
139
+ process_template fp.file_list.first
139
140
 
140
141
  @processor.process_template_alias tracker.templates[template_name]
141
142
 
@@ -390,9 +391,10 @@ class Brakeman::Rescanner < Brakeman::Scanner
390
391
 
391
392
  def parse_ruby_files list
392
393
  paths = list.select(&:exists?)
393
- file_parser = Brakeman::FileParser.new(tracker)
394
- file_parser.parse_files paths, :rescan
395
- file_parser.file_list[:rescan]
394
+ file_parser = Brakeman::FileParser.new(tracker.app_tree, tracker.options[:parser_timeout])
395
+ file_parser.parse_files paths
396
+ tracker.add_errors(file_parser.errors)
397
+ file_parser.file_list
396
398
  end
397
399
  end
398
400
 
@@ -7,6 +7,7 @@ begin
7
7
  require 'brakeman/app_tree'
8
8
  require 'brakeman/file_parser'
9
9
  require 'brakeman/parsers/template_parser'
10
+ require 'brakeman/processors/lib/file_type_detector'
10
11
  rescue LoadError => e
11
12
  $stderr.puts e.message
12
13
  $stderr.puts "Please install the appropriate dependency."
@@ -23,7 +24,10 @@ class Brakeman::Scanner
23
24
  @app_tree = Brakeman::AppTree.from_options(options)
24
25
 
25
26
  if (!@app_tree.root || !@app_tree.exists?("app")) && !options[:force_scan]
26
- raise Brakeman::NoApplication, "Please supply the path to a Rails application (looking in #{@app_tree.root})."
27
+ message = "Please supply the path to a Rails application (looking in #{@app_tree.root}).\n" <<
28
+ " Use `--force` to run a scan anyway."
29
+
30
+ raise Brakeman::NoApplication, message
27
31
  end
28
32
 
29
33
  @processor = processor || Brakeman::Processor.new(@app_tree, options)
@@ -43,6 +47,8 @@ class Brakeman::Scanner
43
47
  process_config
44
48
  Brakeman.notify "Parsing files..."
45
49
  parse_files
50
+ Brakeman.notify "Detecting file types..."
51
+ detect_file_types
46
52
  Brakeman.notify "Processing initializers..."
47
53
  process_initializers
48
54
  Brakeman.notify "Processing libs..."
@@ -65,29 +71,47 @@ class Brakeman::Scanner
65
71
  end
66
72
 
67
73
  def parse_files
68
- fp = Brakeman::FileParser.new tracker
69
-
70
- files = {
71
- :initializers => @app_tree.initializer_paths,
72
- :controllers => @app_tree.controller_paths,
73
- :models => @app_tree.model_paths
74
- }
75
-
76
- unless options[:skip_libs]
77
- files[:libs] = @app_tree.lib_paths
78
- end
74
+ fp = Brakeman::FileParser.new(tracker.app_tree, tracker.options[:parser_timeout])
79
75
 
80
- files.each do |name, paths|
81
- fp.parse_files paths, name
82
- end
76
+ fp.parse_files tracker.app_tree.ruby_file_paths
83
77
 
84
78
  template_parser = Brakeman::TemplateParser.new(tracker, fp)
85
79
 
86
- fp.read_files(@app_tree.template_paths, :templates) do |path, contents|
80
+ fp.read_files(@app_tree.template_paths) do |path, contents|
87
81
  template_parser.parse_template path, contents
88
82
  end
89
83
 
90
- @file_list = fp.file_list
84
+ # Collect errors raised during parsing
85
+ tracker.add_errors(fp.errors)
86
+
87
+ @parsed_files = fp.file_list
88
+ end
89
+
90
+ def detect_file_types
91
+ @file_list = {
92
+ controllers: [],
93
+ initializers: [],
94
+ libs: [],
95
+ models: [],
96
+ templates: [],
97
+ }
98
+
99
+ detector = Brakeman::FileTypeDetector.new
100
+
101
+ @parsed_files.each do |file|
102
+ if file.is_a? Brakeman::TemplateParser::TemplateFile
103
+ @file_list[:templates] << file
104
+ else
105
+ type = detector.detect_type(file)
106
+ unless type == :skip
107
+ if @file_list[type].nil?
108
+ raise type.to_s
109
+ else
110
+ @file_list[type] << file
111
+ end
112
+ end
113
+ end
114
+ end
91
115
  end
92
116
 
93
117
  #Process config/environment.rb and config/gems.rb
@@ -115,6 +139,8 @@ class Brakeman::Scanner
115
139
  if @app_tree.exists? ".ruby-version"
116
140
  tracker.config.set_ruby_version @app_tree.file_path(".ruby-version").read
117
141
  end
142
+
143
+ tracker.config.load_rails_defaults
118
144
  end
119
145
 
120
146
  def process_config_file file
@@ -325,8 +351,11 @@ class Brakeman::Scanner
325
351
  end
326
352
 
327
353
  def parse_ruby_file file
328
- fp = Brakeman::FileParser.new(self.tracker)
354
+ fp = Brakeman::FileParser.new(tracker.app_tree, tracker.options[:parser_timeout])
329
355
  fp.parse_ruby(file.read, file)
356
+ rescue Exception => e
357
+ tracker.error(e)
358
+ nil
330
359
  end
331
360
  end
332
361
 
@@ -35,6 +35,7 @@ class Brakeman::Tracker
35
35
  #class they are.
36
36
  @models = {}
37
37
  @models[UNKNOWN_MODEL] = Brakeman::Model.new(UNKNOWN_MODEL, nil, @app_tree.file_path("NOT_REAL.rb"), nil, self)
38
+ @method_cache = {}
38
39
  @routes = {}
39
40
  @initializers = {}
40
41
  @errors = []
@@ -68,6 +69,12 @@ class Brakeman::Tracker
68
69
  }
69
70
  end
70
71
 
72
+ def add_errors exceptions
73
+ exceptions.each do |e|
74
+ error(e)
75
+ end
76
+ end
77
+
71
78
  #Run a set of checks on the current information. Results will be stored
72
79
  #in Tracker#checks.
73
80
  def run_checks
@@ -93,8 +100,8 @@ class Brakeman::Tracker
93
100
  classes.each do |set|
94
101
  set.each do |set_name, collection|
95
102
  collection.each_method do |method_name, definition|
96
- src = definition[:src]
97
- yield src, set_name, method_name, definition[:file]
103
+ src = definition.src
104
+ yield src, set_name, method_name, definition.file
98
105
  end
99
106
  end
100
107
  end
@@ -214,6 +221,34 @@ class Brakeman::Tracker
214
221
  nil
215
222
  end
216
223
 
224
+ def find_method method_name, class_name, method_type = :instance
225
+ return nil unless method_name.is_a? Symbol
226
+
227
+ klass = find_class(class_name)
228
+ return nil unless klass
229
+
230
+ cache_key = [klass, method_name, method_type]
231
+
232
+ if method = @method_cache[cache_key]
233
+ return method
234
+ end
235
+
236
+ if method = klass.get_method(method_name, method_type)
237
+ return method
238
+ else
239
+ # Check modules included for method definition
240
+ # TODO: only for instance methods, otherwise check extends!
241
+ klass.includes.each do |included_name|
242
+ if method = find_method(method_name, included_name, method_type)
243
+ return (@method_cache[cache_key] = method)
244
+ end
245
+ end
246
+
247
+ # Not in any included modules, check the parent
248
+ @method_cache[cache_key] = find_method(method_name, klass.parent)
249
+ end
250
+ end
251
+
217
252
  def index_call_sites
218
253
  finder = Brakeman::FindAllCalls.new self
219
254
 
@@ -279,8 +314,8 @@ class Brakeman::Tracker
279
314
  method_sets.each do |set|
280
315
  set.each do |set_name, info|
281
316
  info.each_method do |method_name, definition|
282
- src = definition[:src]
283
- finder.process_source src, :class => set_name, :method => method_name, :file => definition[:file]
317
+ src = definition.src
318
+ finder.process_source src, :class => set_name, :method => method_name, :file => definition.file
284
319
  end
285
320
  end
286
321
  end
@@ -1,4 +1,5 @@
1
1
  require 'brakeman/util'
2
+ require 'brakeman/tracker/method_info'
2
3
 
3
4
  module Brakeman
4
5
  class Collection
@@ -13,6 +14,7 @@ module Brakeman
13
14
  @src = {}
14
15
  @includes = []
15
16
  @methods = { :public => {}, :private => {}, :protected => {} }
17
+ @class_methods = {}
16
18
  @options = {}
17
19
  @tracker = tracker
18
20
 
@@ -46,11 +48,16 @@ module Brakeman
46
48
  end
47
49
 
48
50
  def add_method visibility, name, src, file_name
51
+ meth_info = Brakeman::MethodInfo.new(name, src, self, file_name)
52
+
49
53
  if src.node_type == :defs
54
+ @class_methods[name] = meth_info
55
+
56
+ # TODO fix this weirdness
50
57
  name = :"#{src[1]}.#{name}"
51
58
  end
52
59
 
53
- @methods[visibility][name] = { :src => src, :file => file_name }
60
+ @methods[visibility][name] = meth_info
54
61
  end
55
62
 
56
63
  def each_method
@@ -61,16 +68,31 @@ module Brakeman
61
68
  end
62
69
  end
63
70
 
64
- def get_method name
65
- each_method do |n, info|
66
- if n == name
67
- return info
71
+ def get_method name, type = :instance
72
+ case type
73
+ when :class
74
+ get_class_method name
75
+ when :instance
76
+ get_instance_method name
77
+ else
78
+ raise "Unexpected method type: #{type.inspect}"
79
+ end
80
+ end
81
+
82
+ def get_instance_method name
83
+ @methods.each do |_vis, meths|
84
+ if meths[name]
85
+ return meths[name]
68
86
  end
69
87
  end
70
88
 
71
89
  nil
72
90
  end
73
91
 
92
+ def get_class_method name
93
+ @class_methods[name]
94
+ end
95
+
74
96
  def file
75
97
  @files.first
76
98
  end
@@ -149,5 +149,78 @@ module Brakeman
149
149
  def session_settings
150
150
  @rails.dig(:action_controller, :session)
151
151
  end
152
+
153
+
154
+ # Set Rails config option value
155
+ # where path is an array of attributes, e.g.
156
+ #
157
+ # :action_controller, :perform_caching
158
+ #
159
+ # then this will set
160
+ #
161
+ # rails[:action_controller][:perform_caching] = value
162
+ def set_rails_config value, *path
163
+ config = self.rails
164
+
165
+ path[0..-2].each do |o|
166
+ config[o] ||= {}
167
+
168
+ option = config[o]
169
+
170
+ if not option.is_a? Hash
171
+ Brakeman.debug "[Notice] Skipping config setting: #{path.map(&:to_s).join(".")}"
172
+ return
173
+ end
174
+
175
+ config = option
176
+ end
177
+
178
+ config[path.last] = value
179
+ end
180
+
181
+ # Load defaults based on config.load_defaults value
182
+ # as documented here: https://guides.rubyonrails.org/configuring.html#results-of-config-load-defaults
183
+ def load_rails_defaults
184
+ return unless number? tracker.config.rails[:load_defaults]
185
+
186
+ version = tracker.config.rails[:load_defaults].value
187
+ true_value = Sexp.new(:true)
188
+ false_value = Sexp.new(:false)
189
+
190
+ if version >= 5.0
191
+ set_rails_config(true_value, :action_controller, :per_form_csrf_tokens)
192
+ set_rails_config(true_value, :action_controller, :forgery_protection_origin_check)
193
+ set_rails_config(true_value, :active_record, :belongs_to_required_by_default)
194
+ # Note: this may need to be changed, because ssl_options is a Hash
195
+ set_rails_config(true_value, :ssl_options, :hsts, :subdomains)
196
+ end
197
+
198
+ if version >= 5.1
199
+ set_rails_config(false_value, :assets, :unknown_asset_fallback)
200
+ set_rails_config(true_value, :action_view, :form_with_generates_remote_forms)
201
+ end
202
+
203
+ if version >= 5.2
204
+ set_rails_config(true_value, :active_record, :cache_versioning)
205
+ set_rails_config(true_value, :action_dispatch, :use_authenticated_cookie_encryption)
206
+ set_rails_config(true_value, :active_support, :use_authenticated_message_encryption)
207
+ set_rails_config(true_value, :active_support, :use_sha1_digests)
208
+ set_rails_config(true_value, :action_controller, :default_protect_from_forgery)
209
+ set_rails_config(true_value, :action_view, :form_with_generates_ids)
210
+ end
211
+
212
+ if version >= 6.0
213
+ set_rails_config(Sexp.new(:lit, :zeitwerk), :autoloader)
214
+ set_rails_config(false_value, :action_view, :default_enforce_utf8)
215
+ set_rails_config(true_value, :action_dispatch, :use_cookies_with_metadata)
216
+ set_rails_config(false_value, :action_dispatch, :return_only_media_type_on_content_type)
217
+ set_rails_config(Sexp.new(:str, 'ActionMailer::MailDeliveryJob'), :action_mailer, :delivery_job)
218
+ set_rails_config(true_value, :active_job, :return_false_on_aborted_enqueue)
219
+ set_rails_config(Sexp.new(:lit, :active_storage_analysis), :active_storage, :queues, :analysis)
220
+ set_rails_config(Sexp.new(:lit, :active_storage_purge), :active_storage, :queues, :purge)
221
+ set_rails_config(true_value, :active_storage, :replace_on_assign_to_many)
222
+ set_rails_config(true_value, :active_record, :collection_cache_versioning)
223
+ end
224
+ end
152
225
  end
153
226
  end