Brakeman - Rails Security Scanner

Static analysis security scanner for Ruby on Rails

Brakeman 1.6 Released

A lot of code has changed in this release, particularly with the removal of the Ruport library for reporting. While Ruport worked pretty well, it caused some issues just due to the large number of (out-dated) dependencies it brought with it.

Also, this release changes the JSON report output. This is a backwards incompatible change. But, given how useless the previous JSON reports were, hopefully this will not affect too many people.

Changes since 1.5.3:

  • Remove the Ruport dependency (Neil Matatall)
  • Add more informational JSON output (Neil Matatall)
  • Add comparison to previous JSON report (Neil Matatall)
  • Add highlighting of dangerous values in HTML/text reports
  • Model#update_attribute should not raise mass assignment warning (Dave Worth)
  • Don’t check find_by_* method for SQL injection
  • Fix duplicate reporting of mass assignment and SQL injection
  • Fix rescanning of deleted files
  • Properly check for rails_xss in Gemfile

No More Ruport

Ruport is a nice library, but it also has not been updated in over two years and its dependency tree was ridiculous.

Thanks to Neil Matatall, Brakeman no longer depends on Ruport, but the reports should look essentially the same. The HTML reports are now rendered through ERB templates, so it should not be too difficult to customize the reports if desired.

Better JSON Output

JSON output now includes meta-information about the scan, errors raised during the scan, and line numbers for each warning.

JSON Report Comparison

Being able to compare Brakeman reports is essential for tracking warnings over time. Prior to this release, the only decent way of doing that was via the Jenkins plugin. But now Brakeman can compare results to the JSON report from a previous scan.

For example:

brakeman -o report.json
brakeman --compare report.json

This will run another scan, then output a comparison of the reports (in JSON). The report includes a list of fixed warnings and a list of new warnings that were found.

User Input Highlighted in Reports

Sometimes it is unclear exactly what value has caused Brakeman to issue a particular warning. This release adds highlighting the detected user input in most warnings. (Some warnings, the code that is reported is the detected user input). This information is also available in the JSON reports.

User Input Highlight

Fewer Mass Assignment and SQL Injection Methods

Dave Worth pointed out that Brakeman was a little overzealous in which methods it considered susceptible to mass assignment and SQL injection attacks.

Brakeman will no longer check update_attribute for mass assignment or the find_by_* dynamic methods for SQL injection.

Fewer Mass Assignment and SQL Injection Duplicates

Pesky duplicate reports of mass assignment and SQL injection were turning up as template warnings. This occurred when the results of the mass assignment or SQL query were assigned to a variable which was then used in a template. This should now be fixed.

More details than are probably desired are available here.

Rescanning Fixes

Rescanning of deleted files is now supported, and there some other issues with rescanning that are now resolved as well.

New Logo

Brakeman has a sweet new logo, thanks to Janelle Lawless!

Brakeman Logo

Updates to the website to reflect this awesomeness are coming soon.

Reporting Issues

Please report any issues with this release!

Also consider joining the mailing list or following @brakeman on Twitter.

And don’t forget to check out the Brakeman talk at RailsConf in a few days.

Brakeman 1.5.3 Released

A considerable number of bugs and odd cases have been fixed with this release, and one new check has been added. Upgrading is always recommended!

Changes since 1.5.2:

  • Add check for user input in Object#send (Neil Matatall)
  • Support output to multiple formats (Nick Green)
  • Prevent infinite loops in mutually recursive templates
  • Only check eval arguments for user input, not the call target
  • Handle render :layout in views
  • Search subdirectories for models
  • Set values in request hashes and propagate to views
  • Add rake task file to gemspec (Anton Ageev)
  • Filter rescanning of templates (Neil Matatall)
  • Improve handling of modules and nesting
  • Test for zero errors in test reports

New Check for User Input in Object#send

This new check looks for instances where user input can be used to control the method called using send.

For example:

user = User.find(params[:user][:id])
method = params[:user][:action].to_sym
user.send(method)

Support for Multiple Output Formats

Brakeman can now accept multiple -o arguments in order to produce more than one report from the same scan:

brakeman -o report.html -o report.json

Handle Mutually Recursive Templates

In some cases where two templates would render each other as partials, it would cause infinite loops in Brakeman. This is now fixed, at least for the simple common case:

_one.erb.html:

<%= render :partial => 'two' %>

_two.erb.html:

<%= render :partial => 'one' %>

Only Check eval Arguments

Previously, Brakeman was checking the entire call to methods like eval or class_eval for user input. This led to false positives when class_eval was being called on a model.

Now Brakeman only checks the arguments or block provided to the eval call.

Handle render :layout in views

Brakeman was not handling render :layout => "..." in views properly. This led to errors like:

wrong number of arguments (0 for 1): /Users/collins/work/brakeman/lib/brakeman/processors/lib/render_helper.rb:14:in `template_name

render :layout is now handled just like rendering a partial.

Search for Models in Subdirectories

Brakeman was only searching app/models/ for models, but not any subdirectories. Now it does!

Propagate Request Values

While Brakeman has always detected request values (e.g., query parameters) in views, it would not propagate values stored IN those request hashes.

For example, if an action in a controller did this:

params[:input] = some_random_value

That value would not be propagated to the view if the view used params[:input].

Add Rake Task to Gemspec

In 1.2.0, Brakeman added the --rake option to add a Rake task to a Rails application, but the actual task itself was not included in the gem!

Thanks to Anton Ageev for pointing this out. Either no one else tried this option, or a lot of people were very disappointed.

Filter Templates When Rescanning

When rescanning (for example, with guard-brakeman), Brakeman was assuming any files in app/views is a template, but this isn’t always true.

Reporting Issues

Please report any issues!

Also consider joining the mailing list or following @brakeman on Twitter.

And don’t forget to check out the Brakeman talk at RailsConf later this month.

Brakeman 1.5.2 Released - Important Fixes

This is update includes some important fixes. All users of the rails_xss plugin are particularly encouraged to upgrade.

Changes since 1.5.1:

  • Fix handling of views when using rails_xss
  • Fix rescanning of lib files (Neil Matatall)
  • Fix link_to checks for Rails 2.0 and 2.3
  • Revert to ruby_parser 2.3.1 for Ruby 1.8 parsing
  • Only warn on user input in render paths
  • Output stack trace on interrupt when debugging
  • Ignore user input in if statement conditions
  • Fix –skip-files option with Ruby 1.8

Views with rails_xss

Some previous changes to make sure Brakeman was processing ERB views the same way as the rails_xss plugin unfortunately broke the processing of those views.

These changes caused Brakeman to not report any output from ERB views when the rails_xss plugin was in use, hiding any XSS vulnerabilities in those views.

This now fixed, so if you are using the rails_xss plugin, it is highly recommended to upgrade.

Rescanning lib/ Files

Rescanning changed files in the lib directory was broken, but Neil fixed it!

link_to Checks

In Rails 2.3, the URL is escaped, but not the body of the link. In Rails 2.0, neither argument is escaped.

In this release, the check for XSS in link_to has been updated to handle link_to with blocks and to warn in Rails 2.0.x if any user input is used as an argument.

Revert to ruby_parser for Ruby 1.8

Brakeman has been using a vendored version of ruby_parser with some updates to Ruby 1.9 syntax parsing. Unfortunately, that version also introduced some regressions for parsing Ruby 1.8 syntax.

To handle this, Brakeman will now only use the vendored version for 1.9 parsing, but the regular gem version for 1.8 syntax parsing. This should fix some parse errors people are seeing for Ruby 1.8 apps.

Dynamic Render Path Updates

The check for dynamic render paths was not very good, but it is better now. “Dynamic Render Path” warnings should only be raised when user input is actually used to determine what view, partial, or file to render.

Stacktrace Output

Brakeman will now output a stacktrace if interrupted while running with the -d option. This is mostly helpful when Brakeman appears to “hang”.

Reporting Issues

Please report any issues!

Also consider joining the mailing list or following @brakeman on Twitter.

Brakeman Jenkins Plugin 0.7 Released

The Jenkins/Hudson plugin which tracks, displays, and alerts on Brakeman warnings has been updated to work with the latest static analysis core plugin. In particular, this means warning thresholds for new warnings will no longer disappear.

See here for more information about the plugin.

Thanks to Nick Green for fixing this!

Brakeman 1.5.1 Released

After the excitment yesterday with a mass assignment vulnerability being exploited in a very public manner on Github, interest in Brakeman has skyrocketed.

This lead to re-examination of Brakeman’s code for detecting that mass assignment has been globally disabled - and it turns out there was a bug or two. So here is a bug-fix release of Brakeman to correct that and some other minor issues.

Upgrading to 1.5.1 may increase the number of warnings reported.

Changes since 1.5.0:

  • Fix detection of global mass assignment setting
  • Fix partial rendering in Rails 3
  • Show backtrace when interrupt received (Ruby 1.9 only)
  • More debug output
  • Internal fixes:
    • Remove duplicate method in Brakeman::Rails2XSSErubis
    • Add tracking of module and class to Brakeman::BaseProcessor
    • Report module when using Brakeman::FindCall

Mass Assignment

Mass assignment is not a particularly new issue, but the amount of attention suddenly focused on it this weekend was amazing.

This release of Brakeman can detect three different methods for defaulting all models to a whitelist of allowed attributes that can be mass assigned.

The first is probably the most widely-seen version. In an intializer, do

ActiveRecord::Base.send(:attr_accessible, nil)

The second is essentially equivalent, but 1.5.1 adds support for it as well:

module ActiveRecord
  class Base
    attr_accessible nil
  end
end

The third option is only available for Rails 3.1.0 and newer. The following configuration setting can be added to application.rb:

config.active_record.whitelist_attributes = true

Brakeman should correctly detect all of these.

This is a very nice post explaining the dangers of mass assignment (mentioning Brakeman is nice, too.)

Partials in Rails 3

In Rails 3, render 'blah' is now equivalent to render :partial => 'blah' when used inside a template.

Brakeman now supports this correctly.

Debug Output

More debugging output has been added for use with the -d option.

Additionally, when interrupting the application (for example, with ^C), a stack trace will be output. Please note, however, that this only works with Ruby 1.9.

Internal Changes

There have been a few internal changes. There is a possibility that these will affect some warnings. However, it should only result in accurate reporting of class names.

Report Issues

Please report any problems on Github!

Brakeman 1.5.0 Released

A release was forced today because two new Rails vulnerabilities were reported (the first since November):

This release includes checks for these two vulnerabilities.

There is also a new check for skipping CSRF token verification, and some other changes which may result in fewer or more vulnerabilities being reported.

Changes since 1.4.0:

  • Add version check for SafeBuffer vulnerability
  • Add check for select vulnerability in Rails 3
  • select() is no longer considered safe in Rails 2
  • Add check for skipping CSRF protection with a blacklist
  • Add JSON report format
  • Model#id should not be considered XSS
  • Standardize methods to check for SQL injection
  • Fix Rails 2 route parsing issue with nested routes

Check for SafeBuffer Vulnerability

A new vulnerability was reported that affects strings which are marked as html_safe and then modified in some way. For some operations, the new, modified string will still be marked as html_safe. Full details here.

For this vulnerability, Brakeman only does a version check and reports if an application is used a vulnerable version of Rails. It only reports on Rails 3 applications, since Rails 3 introduced the concept of SafeBuffers.

Check for select Helper Vulnerability

Another vulnerability was reported today in the select form helper. Option tags built by hand (interpolating values into <option></option>) will not be escaped by select. Full details here.

For Rails 3 applications, Brakeman checks for uses of select which have user input in the options argument. This check may be refined in the future.

For Rails 2, Brakeman no longer considers select a safe method when checking for cross site scripting.

Check for CSRF Filter Skipping

When cross site request forgery protection is enabled, a before_filter is added called verify_authenticity_token. This filter checks that actions called responding to a POST have a correct authenticity token from the client. Since this is a regular before_filter, it can be skipped using skip_before_filter.

If skip_before_filter is called using an :except option, then the default for the controller becomes NOT checking for an authenticity token:

skip_before_filter :verify_authenticity_token, :except => [:create, :delete]

It is recommended to use :only if skipping this filter is actually necessary. This way, any new actions added later will automatically fall under the CSRF protection.

This check may be extended in the future to other important filters.

JSON Report Format

While the code for outputting JSON was in the 1.4.0 release, it was not actually added as a proper output format! This has been rectified.

-f json or -o report.json will now produce JSON reports.

The information contained in these reports may change in the future, although that should only be adding more information.

SQL Methods

The code for finding SQL methods to check for SQL injection was a little messed up. Depending on how the method was called, different sets of methods were considered dangerous.

This has been changed for better consistency and coverage. This means reports may include new SQL injections, so keep an eye out.

Rails 2 Route Parsing Fix

There was a bug in the code which determined if a method was being called on map, which caused Brakeman to think strange methods were route definitions (for example, require). This has been fixed.

Report Problems!

Always report problems encountered when running Brakeman.

Don’t forget to join the mailing list and/or follow @Brakeman on Twitter.

Brakeman 1.4.0 Released

This is not a big release, but it does add a new check. Also, processing for ERB templates with the rails_xss plugin has changed, so there is the possibility that line numbers for reported warnings will shift.

Changes since 1.3.0:

  • Add check for user input in link_to href parameter
  • Match ERB processing to rails_xss plugin when plugin used
  • Add Brakeman::Report#to_json, Brakeman::Warning#to_json
  • Warnings below minimum confidence are dropped completely
  • Brakeman.run will now always return a Tracker

New Check for link_to

Neil Matatall has contributed a new check for the href parameter in link_to. Even if HTML escaped, some values can be dangerous, so this check will warn for user input in that parameter. See here for more details.

The --url-safe-methods option can be used to specify escaping methods which are safe for urls.

ERB and rails_xss

The rails_xss plugin has some fixes for how Erbuis handles certain input. Brakeman now matches those changes, which fixes some parsing errors.

Internal Changes

There have been some changes which only impact those working with Brakeman as a library.

First, there is now json output for reports. This actually should be an output format option, but I did not realize it until writing this post. The next release will include this, though!

The way Brakeman handles the --confidence-level option has also changed. In the past, warnings would be filtered when output in a report. This meant, for example, that tracker.checks.all_warnings would still return warnings below the specified confidence level. It also caused problems because there were many places in the code where the warnings needed to be filtered. With this release, warnings below the confidence level will be dropped as soon as they are found and will not need to be filtered at any later point.

Lastly, Brakeman.run would return false if --exit-on-warn was set, and a Tracker object otherwise. This has changed. Brakeman.run will now always return a Tracker object and the logic for --exit-on-warn was pushed out to the Brakeman executable.

Report Issues

As usual, please report any issues.

Brakeman 1.3.0 Released

Thanks to everyone who reported problems and suggestions this time around!

This release includes some new features, better performance on large projects, and more detection criteria. Warnings reported may change after upgrading.

Changes since 1.2.2:

  • Add file paths to HTML report
  • Add caching of filters
  • Add --skip-files option
  • Add support for attr_protected
  • Add detection of request.env as user input
  • Descriptions of checks in -k output
  • Improved processing of named scopes
  • Check for mass assignment in ActiveRecord::Associations::AssociationCollection#build
  • Better variable substitution
  • Table output option for rescan reports

File Paths in HTML Report

In the HTML output, any warning which has context associated with it (visible when clicking on the warning message) will now include the file name at the top of the code snippet.

Filter Caching

Filters (using before_filter) are now only parsed once, instead of for everytime they are used. This has greatly improved performance when scanning some large projects.

Option to Skip Files

A list of files to skip can be provided with the --skip-files option. This will skip any initializers, libraries, controllers, models, or views that match the file names provided. The file names to skip are matched against the end of the absolute path. That is, blah.rb will skip any file with a name ending in blah.rb. This means it is not necessary to provide the full path to a file.

Support for Blacklisting Attributes

Previously, Brakeman ignored uses of attr_protected. Ideally, attr_accessible should always be used to whitelist attributes that can be set using mass assignment. This way, attributes can never be “accidentally” exposed. However, it can also be tedious for large models.

With this release, Brakeman will downgrade mass assignment warnings to “weak” confidence if attr_protected is used, as well as suggesting that attr_accessible be used instead.

The --ignore-protected option can be used to suppress any warnings for models that use attr_protected.

Request Environment is User Input

request.env will now be treated as user input.

Check Descriptions

The -k option now includes descriptions of each check.

Named Scope Improvements

The 1.2.0 release added checking for SQL injection in named scopes, but it was not very accurate. This has been improved.

Better Variable Substitution

Variable substitution would sometimes “explode” if a set of code was processed for aliasing several times.

For example,

x = clean(x)

puts x

Might become

x = clean(x)

puts clean(clean(clean(clean(x))))

This should now be prevented, so it would just become

x = clean(x)

puts clean(x)

There may be subtle issues with this code (although I have not seen any yet), but it’s better than creating a bunch of useless substitutions.

Table Output for Rescan Reports

RescanReport#to_s(true) will now output formatted tables, thanks to Dave Worth.

Issues?

As usual, please report any issues on GitHub, send a tweet to @Brakeman, or send an email to the mailing list.

Brakeman 1.2.2 Released

Changes since 1.2.1:

  • –no-progress works again
  • Make CheckLinkTo a separate check
  • Don’t fail on unknown options to resource(s)
  • Handle empty resource(s) blocks
  • Add RescanReport#existing_warnings

No Progress Option

The last release broke the --no-progress option for hiding the 1/100 files processed type messages. Now it works again!

Separate Check for link_to

For no great reason, CheckLinkTo was bundled with CheckCrossSiteScripting. It has now been moved out to a separate file, allowing it to be treated as a regular check. This means it can be explicitly skipped using -x CheckLinkTo (if desired).

Better Rails 2 Route Handling

Brakeman was raising an exception if a hash option to resource or resources did not match a set of known options. Now it will only warn instead of aborting route processing.

Brakeman 1.2.1 Released

This is essentially just a bugfix release, but due to the fixes for link_to warnings, there is a good possibility the number of reported warnings will decrease when upgrading to this version.

Changes since 1.2.0:

  • Remove link_to warning for Rails 3.x or when using rails_xss
  • Don’t warn if first argument to link_to is escaped
  • Detect usage of attr_accessible with no arguments
  • Fix error when rendering a partial from a view but not through a controller
  • Fix some issues with rails_xss, CheckCrossSiteScripting, and CheckTranslateBug
  • Simplify Brakeman Rake task
  • Avoid modifying $VERBOSE
  • Add Brakeman::RescanReport#to_s
  • Add Brakeman::Warning#to_s

link_to Changes

Prior to Rails 3.0, there was a bug in link_to that caused the body of the link tag to be output without escaping. While this was fixed in Rails 3.0, Brakeman has still been warning on it. This was also fixed in the rails_xss, so Brakeman should no longer warn on link_to for Rails 2.x when using the rails_xss plugin.

Brakeman was also warning on link_to even if the body argument was manually escaped. This should be resolved now.

One other related issue was a silly bug causing Brakeman to sometimes ignore --escape-html or the rails_xss plugin, leading to some confusing output. This is fixed.

Thanks to Neil Matatall for reporting the link_to issue and Andreas for reporting the rails_xss problems.

attr_accessible with No Arguments

Brakeman was not detecting the case where attr_accessible is called with zero arguments, causing spurious mass assignment warnings.

Thanks to Justin Wiley for reporting this.

Brakeman Rake Task

The Brakeman Rake task (installed via --rake) is even simpler now.

$VERBOSE

Brakeman was using $VERBOSE and Kernel.warn for controlling debug output. This has changed and $VERBOSE will no longer be modified when using Brakeman.

Rails 3.2 Support

So far, there have not been any issues with Brakeman and Rails 3.2. Please report any that come up!

JRuby Performance

Prior to Brakeman 1.2, JRuby was very slow when running Brakeman. This has changed, and now JRuby is probably the fastest option for scanning large applications. Give it a try, especially if you are using Ruby 1.8.7!

Mailing List

There is now a Brakeman mailing list on librelist.

To subscribe, send any email to brakeman@librelist.com. You will be asked to confirm your subscription.

Archives are available for browsing on The Mail Archive.