Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ruby check-unsafe-reflection-methods false positive for "some_value.tap" #2915

Open
1 task done
nightpool opened this issue May 11, 2023 · 1 comment
Open
1 task done
Labels
bug Something isn't working

Comments

@nightpool
Copy link

Describe the bug
Brakeman has a rule designed to catch the unsafe usage of tap using a "blockified" symbol generated from user input. For example, the following code is vulnerable, because it relies on using user input to determine which method to call:

  User.new.tap(&params[:method].to_sym)

https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_unsafe_reflection_methods.rb

In fact, the actual vulnerable code in this case is the & operator itself. This operator is designed to turn a symbol into a "block" by referencing the function with the same name as the symbol. This would be an issue when using & on any symbol derived from user input, not just ones passed to tap (tap is just one of the most common cases). For example, User.all.map(&params[:method].to_sym) would be similarly vulnerable.

However, the Semgrep rule this was turned into is very overly broad—it flags as a security vulnerability any usage of the tap method at all even when such usage doesn't involve reflection. For example, it flags params[:user_id].to_i.tap { |user_id| Notifier.remind_user(user_id) } as "vulnerable code", even thought that code doesn't contain any reflection whatsoever.

This is a deviation between the brakeman rule (which checks whether user-input variable is provided as an argument to the tap function, e.g. .tap(user_input)), and the semgrep rule, which appears to flag whether the user input is used as the receiver of the tap function.

This can get extremely silly, for example, this simplified example of a place this rule was flagged by Semgrep in our codebase:

  def load_page_data(target, **options)
    rendering_context = {campaign_override: params[:campaign_override]}
    options = options.merge(rendering_context: rendering_context)
    serialize_data(target, options).tap do |serialized_data|
      log_data_layer if serialized_data[:has_data_layer]
    end
  end

To Reproduce

# ok: check-unsafe-reflection-methods
params[:user_id].to_i.tap { }

Expected behavior

Test passes.

Priority
How important is this to you?

  • P2: annoying but not blocking me
@nightpool nightpool added the bug Something isn't working label May 11, 2023
@nightpool
Copy link
Author

I believe this was fixed by @normprovost in this PR: #3265

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Development

No branches or pull requests

2 participants
@nightpool and others