I have a strange error in my rails application that is being triggered by someone probably doing something they shouldn’t be doing. But I can’t figure out what they might be doing and thus how to guard against it.
The current setup is Rails 7.1.3.2, Ruby 3.3.1, though I’ve seen it for months including being back on Rails 7.0 with Ruby 3.2
Ultimately, I get the following error:
ActionController::ParameterMissing: param is missing or the value is empty: organization
And if I look at the logs, I get the following sequence of requests.
INFO -- Started POST "/o" for 47.238.233.78 at 2024-05-14 17:37:48 +0000
Processing by OrganizationsController#create as */*
INFO -- Parameters: {"authenticity_token"=>"[FILTERED]", "organization"=>{"a1"=>"v1", "a2"=>"v2"}
, "commit"=>"Continue"}
INFO -- <successful redirect>
...
INFO -- Started POST "/o" for 47.238.233.78 at 2024-05-14 17:37:51 +0000
INFO -- Processing by OrganizationsController#create as */*
INFO -- Parameters: {"authenticity_token"=>"[FILTERED]", "organization[a1]"=>"v1", "organization[a2]"=>"v2", "commit"=>"Continue", "organization"=>{}}
INFO -- Completed 400 Bad Request in 1ms
ERROR -- ActionController::ParameterMissing (param is missing or the value is empty: organization)
...
So I can see the empty organization pointing at {}
in the rails log, but if I look at the body of the request in the error, it appears as
..."organization[a1]":"v1","organization[a2]:"v2"..."
with no strange empty assignments like "organization":""
I’ve tried to recreate this a number of different ways, including changing the authenticity_token hidden field in the form before submitting (oddly enough, rails does not have a problem with this). Also resubmitting the same request multiple times using curl (no problem). If I change the value of the session cookie, that does cause an error with rails, but a different one (Can’t verify CSRF token authenticity).
So what could cause rails to act this way? I can certainly handle this error a number of different ways, but I’d like to understand how the user is able to trigger Rails to act this way.