-
Notifications
You must be signed in to change notification settings - Fork 21.6k
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
Strong parameters potential vulnerability #43681
Comments
Can you see if you reproduce it running the instantiation of parameters in a loop? The only way I can see this happening is if the |
Also, since it is flaky spec, maybe it is some monkey patch/mocking in your application? |
@rafaelfranca I checked hashes of both objects. They are different. Also, they even have different I don't think we have I will try to reproduce it in a loop, great point. |
Yeah, I didn't expect you having monkey patches, but the only way I can see this failing is if we have a hash collision, which is very unlikely to happen, but not impossible |
Checked it, can't reproduce in a loop. Can't reproduce in a bash loop with What can be the reason? It indeed might be in the app code but I'm unable to debug it to the C code. Cause the root cause is clearly there. Can anyone at least suggest, what might be the reason? It can be an incorrect pointer in memory, for example, right? Some leak in the C implementation. |
@pyromaniac Equality of elements in a Set is determined according to Object#eql? and Object#hash.
Are you using threads somewhere that could cause a race condition? |
@p8 I don't think so. Set uses a Hash instance internally. Hash uses No, no threads in the surrounding code. |
@pyromaniac I copied that definition straight from the Set documentation: |
Hm, you are right. Then why doesn't it fail in all the cases? Going to check this. Thanks for pointing this out. |
Ok, what I have found so far is:
|
It seems our test suite started reproducing this issue as well https://buildkite.com/rails/rails/builds/83354#5113ba6e-529c-4b73-a639-428fcfc97923/1015-1026 |
I think I've figured this out though I'm not sure how to fix. Applying this patch will make the error from our CI reproduce consistently:
The cause is that we're "converting an array" then inserting that array in to a set. The set is just backed by a hash. When there's a hash miss we "convert the array" (looping through everything and converting it). When there's a hit we don't do that. I think what's happening is that most of the time we're missing the hash lookup, and most of the time we'll just loop through the array and convert the params (meaning that most of the time it just works). However, since we're letting people mutate the underlying array that's stored in the set, it's possible that we get a cache hit and we don't try reconverting anything in the array. Here is kind of a demo: set = {}
key = [Object.new]
set[key] = 1
# mutate the key
key << 1
p set.key?(key) # false cache miss
p set.keys.first == key # true it's the same array We've cached "converted" things in the set, but we let people mutate the cache keys, which poisons the cache. |
Btw, I think the reason that we're seeing this "sometimes" is that hashes will automatically rehash themselves when the underlying hash table needs to resize. So if you insert enough data, eventually you'll see the failure (which I demo'd in the test) |
We don't want to expose these cache keys to users because users can mutate the key causing the cache to behave inconsistently. Fixes: #43681
That's some mindblowing debugging @tenderlove ! |
@tenderlove thanks for diving into this! Hope there will be no issue anymore. But what of the point number 2 in my previous comment? There is still inconsistency between |
Steps to reproduce
Hello everyone. Just stumbled upon a flaky spec. It happens rarely, once in 100-500 cases:
As you can see here, the value returned is not wrapped with
ActionController::Parameters
I dug deeper and found that this line is the reason:
rails/actionpack/lib/action_controller/metal/strong_parameters.rb
Line 941 in 90357af
And the funniest thing is:
I know that hash lookup utilizes
#equal?
along with the#hash
value but they are not#equal?
. They are at most#==
.So I frankly have no idea why does it happen but the bottom line is that in some circumstances strong params can return a raw value which can cause exception if handled and appears to be a potential security risk if not handled.
System configuration
The text was updated successfully, but these errors were encountered: