Brakeman

Ruby on Rails Static Analysis Security Tool

Brakeman 5.0.0 Released

It has been a long time coming, but it is finally here! Lots of changes in this one…

Brakeman now scans (almost) all Ruby (and ERB, Haml, Slim) files in an application. This may have a significant impact on reported warnings and scan times - see below for more information.

Changes since 4.10.1:

  • Scan (almost) all Ruby files in project
  • Revamp CSV report to a CSV list of warnings
  • Add Sonarqube report format (Adam England)
  • Add check for (more) unsafe method reflection (#1488, #1507, and #1508)
  • Add check for potential HTTP verb confusion (#1432)
  • Add --[no-]skip-vendor option
  • Ignore uuid as a safe attribute
  • Ignore Tempfile#path in shell commands
  • Ignore development environment
  • Collapse __send__ calls
  • Set Rails configuration defaults based on load_defaults version
  • Update Ruby requirement to version 2.4.0
  • Suggest using --force if no Rails application is detected

Scan Almost All Ruby Files

Since the beginning, Brakeman has been picky about what directories it searches for files. In general, Brakeman has looked in ‘normal’ Rails directores like app/controllers/, app/models/, app/views/, lib/, config, etc. This is because Rails has some default logic based on file paths - like mapping a controller action to a given view.

But if an application varied from the norm, Brakeman would simply not scan those other directories. This behavior led to a lot of confusion with folks wondering why Brakeman was not finding certain vulnerabilities.

Brakeman now attempts to deduce the contents of a file first, then falls back to the path name if necessary. This has been surprisingly effective.

However, scanning more files means Brakeman runs slower and may report more false positives because the new files are harder to reason about and less likely to be exposed as part of the attack surface.

Brakeman does ignore test, spec, and vendor directories. To scan the vendor directory as well, use --no-skip-vendor.

Please report any issues!

(changes)

CSV Report Update

The CSV report format has been completely changed! Previously, it was meant as an ‘Excel-lite’ format, only really useful for viewing in a spreadsheet program.

Now it is regular CSV with normalized columns to mostly match the JSON report (except for nested fields).

(changes)

Sonarqube Report Format

Thanks to Adam England, Brakeman now supports the Sonarqube “Generic Issue Import Format”.

(And thanks Adam for your patience.)

(changes)

More Unsafe Method Reflection

A new check was added for unsafe use of method, to_proc, and tap.

(changes)

HTTP Verb Confusion Check

In Rails, HEAD requests are routed like GET requests, but request.get? will be false.

Some code may assume if request.get? is false, then request.post? is true:

if request.get?
  # Do something benign
else
  # Do something sensitive because it's a POST
  # but actually it could be a HEAD :(
end

Brakeman will warn when an if expression checks request.get? but has an else clause instead of elseif ....

(changes)

UUIDs as Safe Attributes

#uuid will be treated as a safe value, particular in SQL.

(changes)

Tempfile Paths in Shell Commands

Tempfile#path will be considered as safe value for command injection.

Also adds support for Tempfiles like:

Tempfile.open('...') do |file|
  # Brakeman knows `file` is a Tempfile
end

(changes

Ignore Development Environment

Brakeman will ignore code that is guarded like

if Rails.env.development?
  # ...whatever code
end

This was already true for Rails.env.test?.

(changes)

Collapse __send__ Calls

Brakeman will treat

Blah.__send__(:something, 5.0)

as

Blah.something(5.0)

This was already true for send and try.

(changes)

Set Rails Defaults

Brakeman will set default values for Rails configuration options based on the version argument to config.load_defaults which is usually called in application.rb.

(changes)

Requires Ruby 2.4.0

The minimal Ruby version for running Brakeman is now 2.4.0 (which is already EOL!)

Note Brakeman can analyze Ruby syntax from 1.8 to 2.6 (some 2.7+ syntax is not supported yet).

(changes)

Checksums

The SHA256 sums for this release are:

21b91f67cde4cf487df0a4dbf6e54729064c665bb0b4b370b71bac9435b63e4c  brakeman-5.0.0.gem
3641c52448ca1d12423595ca1a874c1362f438cd58196825be648bb797096cb5  brakeman-lib-5.0.0.gem
50bab26fe8fcf8d962baaf5b08b7c178315b7c0e4be07d1b134e8ae00338c908  brakeman-min-5.0.0.gem

Reporting Issues

Thank you to everyone who reported bugs and contributed to this release!

Please report any issues with this release. Take a look at this guide to reporting Brakeman problems.

Follow @brakeman on Twitter and hang out on Gitter for questions and discussion.

Brakeman 4.10.1 Released

This releases fixes Ruby 3.0 compatibility (meaning running under 3.0, new syntax is not supported yet).

Changes since 4.10.0:

  • Declare REXML as a dependency (Ruby 3.0 compatibility)
  • Use Sexp#sexp_body instead of Sexp#[..] (Ruby 3.0 compatibility)
  • Prevent render loops when template names are absolute paths (#1536)
  • Ensure RubyParser is passed file path as a String (#1534)
  • Support new Haml 5.2.0 escaping method (#1517)

REXML as an Explicit Dependency

In Ruby 3.0, REXML has become a ‘bundled’ gem. It is distributed with Ruby, but if Bundler is involved then it needs to be declared as an explicit dependency.

If you like minimal dependencies, you can always use the brakeman-min gem which declares only strict dependencies.

(changes)

Avoid Slicing with Sexp#[]

Sexp subclasses from Array, and Array no longer returns subclasses from methods that create new arrays.

Brakeman was unfortunately using Sexp#[] with ranges (e.g. s(:a, :b, :c)[1..-1]), which runs into this behavior. Happily, the Sexp#sexp_body method already exists to properly slice and return a Sexp.

(changes)

Recursive Renders with Absolute Paths

Brakeman has long been able to detect recursive render loops, but that detection did not work if the partial name was an ‘absolute’ path.

This is now fixed!

(changes)

Ensure RubyParser Path is a String

In some cases, the parser was given a Brakeman::FilePath for the file name. This only caused an issue in some weird corner cases, but it was wrong nonetheless.

Now Brakeman::FileParser will ensure the file name is passed as a string.

(changes)

Support Haml 5.2

Haml 5.2.0 introduced a new method for escaping output, which caused some false positives.

(Note this was avoided in Brakeman 4.10.0 by bundling an earlier version of Haml.)

(changes)

Checksums

The SHA256 sums for this release are:

e40451080554884a63d73a2933c36518a3cf7a2bb471e6d864ce39a9d3455c98  brakeman-4.10.1.gem
ec69e04e087b74862629e952d7817dd7b73e30810166e01d69d24d7164101455  brakeman-lib-4.10.1.gem
3deee68eadd8eb6850254a8e753d6bbe933194c883f12a2455bdf5fd97b1eba2  brakeman-min-4.10.1.gem

Reporting Issues

Thank you to everyone who reported bugs and contributed to this release!

Please report any issues with this release. Take a look at this guide to reporting Brakeman problems.

Follow @brakeman on Twitter and hang out on Gitter for questions and discussion.

Brakeman 4.10.0 Released

This release introduces a new report format!

Changes since 4.9.1:

SARIF Report Format

Steve Winton from GitHub has contributed support for Static Analysis Results Interchange Format (SARIF). This is a standard format for static analysis tools and can be consumed by some report viewers, such as this one for Visual Studio Code.

To output a SARIF report, use -f sarif or a file name like -o report.sarif.

(changes)

Previewing Brakeman 5.0

What is planned for Brakeman 5.0?

The big change coming in 5.0 is scanning way more files. Currently, Brakeman scans specific directories in app/, config/, lib/, and engines/. It also only looks for files in particular places - e.g. views will be somewhere in app/**/views.

In 5.0, Brakeman will scan (almost) all files in the project directory with .rb or template-related extensions. This will dramatically increase the scope of Brakeman scans, which is better coverage but at the cost of more false positives and slower scans.

Also expected in Brakeman 5.0 is a bump of minimum Ruby version to 2.4.0 (which is already EOL).

Checksums

The SHA256 sums for this release are:

7bef7df71137d06be5fc3325ead57f8ce35be7691bf6dd389228461d731b79dd  brakeman-4.10.0.gem
698b8eb02cdea7a6e407192c261c61d8fc6cd24d590a1b388defc9de17966119  brakeman-lib-4.10.0.gem
64bb565ee84b9a9646985e456db1125ff9fb884ca83de6ba6fbc2c63bdbc8de9  brakeman-min-4.10.0.gem

Reporting Issues

Thank you to everyone who reported bugs and contributed to this release!

Please report any issues with this release. Take a look at this guide to reporting Brakeman problems.

Follow @brakeman on Twitter and hang out on Gitter for questions and discussion.

Brakeman 4.9.1 Released

This release was prompted by the release of ruby_parser 3.15.0, which includes a lot of fixes and improvements, including support for some Ruby 2.7 syntax.

Changes since 4.9.0:

  • Use version from active_record for non-Rails apps (Ulysse Buonomo)
  • Check chomped strings for SQL injection (#1509)
  • Always set line number for joined arrays (#1499)
  • Avoid warning about missing attr_accessible if protected_attributes gem is used (#1512)

Check ActiveRecord Version

For non-Rails applications that are using ActiveRecord, use the version of active_record to set Brakeman’s guess at a Rails version. Thanks to Ulysse Buonomo.

Note: It is not recommended to run Brakeman on non-Rails applications… but no one is going to stop you if you want really to.

(changes)

SQL Injection with Chomp

Brakeman will now check for string interpolation inside strings that have chomp called on them.

(changes)

Joined Arrays Line Number

Fixed a small, unlikely bug where joining two arrays where Brakeman doesn’t have a line number for either of them would raise an exception. Not really sure how that happens, though.

(changes)

Protected Attributes

When using the protected_attributes gem, it is allowed but not required to set attr_accessible on models.

Brakeman will no longer warn about missing attr_accessible when protected_attributes is used.

(changes)

Update RubyParser

As noted above, this version of Brakeman ships with an updated version of ruby_parser.

Checksums

The SHA256 sums for this release are:

5a17706b1da4886f1b6864c3ffff1ab40684f3f7b4d667138227c467ebccb0f7  brakeman-4.9.1.gem
8bb3d88f9786e9f08c24d38e88c40adf02f4a47b17de8c1c816f7e174de476a4  brakeman-lib-4.9.1.gem
8eae3eec1ebab0cf3b29ea50089f613b0d8e544ae4c332f1f5e64a240e8a0a94  brakeman-min-4.9.1.gem

Reporting Issues

Thank you to everyone who reported bugs and contributed to this release!

Please report any issues with this release. Take a look at this guide to reporting Brakeman problems.

Follow @brakeman on Twitter and hang out on Gitter for questions and discussion.

Brakeman Turns Ten!

Hi! Justin Collins here with a rare non-release-related Brakeman post.

On August 27, 2010 (two days before Rails 3.0!), I released the first public version of my summer intern project at AT&T Interactive: a static analysis security tool for Ruby on Rails called “Brakeman”.

Brakeman was intended to be a stop-gap solution until commercial products started supporting Ruby. I had no idea it would take me on such a wild journey nor did I think I would still be maintaining it ten years later.

In the past ten years, Brakeman has had:

I am extremely grateful to everyone who has contributed to this journey: those who took chances on me, those who supported and promoted Brakeman, those who have contributed time and code to Brakeman, those who reported bugs and suggested improvements, and everyone who has used Brakeman to make their applications safer!

Very special thanks to:

Want some Brakeman FAQ nuggets? You got it!

Where did the idea for Brakeman come from?

I recall during my internship interview at AT&T Interactive, we were talking about cross-site scripting. I distinctly recall saying, “What if we had a tool that looked at the inputs and outputs of an application and found cross-site scripting?” The response was an excited “Do you know of a tool like that for Ruby?” To which I replied, “No, but I’m sure it wouldn’t be that hard to build!” This idea was later pitched back to me as a possible internship project.

By the way, that’s still not how Brakeman works, but it was originally designed to find cross-site scripting.

Who came up with the name “Brakeman”?

Carl Johnson and Tatsuya Murase on the security team at AT&T Interactive were way more into trains than me, and they suggested the name. There were a couple other candidates, but I thought “Brakeman” had a snappy sound to it and was unique.

Was Brakeman your PhD research?

Nope, unrelated. However, Brakeman was released exactly at the midpoint of my PhD career.

Here is my dissertation for those interested few.

It’s a brakeman lantern and was designed by Janelle Lawless.

Do you still maintain Brakeman? Who owns it?

Yes, I am still the maintainer of the free version you see here.

The bits of Brakeman owned by Brakeman, Inc. were sold to Synopsys.

Will Brakeman ever support other languages/frameworks?

Almost certainly not. It is very tailored to Ruby and Rails and I don’t have time or energy to build another static analysis engine from scratch!

Can I see a picture of you presenting Brakeman in public for the very first time?

Sure, here you go:

Justin Collins presenting at LA Ruby Meetup October 2010

That’s nice but what about blurry video of the first conference talk about Brakeman?

No problem!

Okay but what I really want is a sweet Brakeman sticker.

Oh, one of these special edition ones?

Metallic Brakeman Sticker

Email your name and physical address to [email protected].

What’s next?

Next is Brakeman 5.0! It would have been nice to have a release coincide with this anniversary, but alas that is way too hard to manage. No promises, but if all goes well 5.0 will be released in September.

As long as Rails continues to hang on as a solid option for many companies and individuals, I expect to continue maintaining Brakeman. The project means a lot to me and it’s a privilege and responsibility I take very seriously.

We’ll see what happens in the next ten years!