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

Regression with empty nested attributes in parameters #8832

Closed
OmarSkalli opened this issue Jan 9, 2013 · 134 comments
Closed

Regression with empty nested attributes in parameters #8832

OmarSkalli opened this issue Jan 9, 2013 · 134 comments
Milestone

Comments

@OmarSkalli
Copy link

Rails 3.2.11 is causing a regression when nested attributes have an empty value. For example, the following code works in 3.2.10 but throws an exception in 3.2.11:

            $.ajax('/home/index', {
                type: 'POST',
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                data: JSON.stringify({ post: { comments_attributes: [] }}),
                error: function(response, status, jqxhr) { $("#response").html(response.responseText); },
                success: function(response, status, jqxhr) { $("#response").html("Request successful"); }
            });
        });

You can reproduce the bug with the following repro application:

This is breaking my application, and other will most likely encounter this exception. This commit is causing the regression: d5cd97b

hash[k] = nil if v.empty
@mattgreen
Copy link

+1

We had to work around this in production just after we deployed 3.2.11. An empty array is a perfectly reasonable value.

@ienders
Copy link

ienders commented Jan 9, 2013

+1

I don't usually comment on issues, but I'm sorry, this is pretty upsetting. An empty array and nil are not the same thing at all.

@akavi
Copy link

akavi commented Jan 9, 2013

+1

Why is the fix in JSON parsing instead of in query generation?

Note that this fix also strips nils from within arrays (eg. [1, 2, 3, nil] => [1, 2, 3])

@PikachuEXE
Copy link
Contributor

Should be related to #8831

@OmarSkalli
Copy link
Author

Definitely related. It's worth pointing however that in this case, an exception is thrown. In #8831, it silently strips nil. Both should definitely be fixed.

@jeremy
Copy link
Member

jeremy commented Jan 9, 2013

Please do investigate! Need a fix that doesn't result in args injection. See the tests @ d5cd97b#L7R27

@homakov
Copy link
Contributor

homakov commented Jan 9, 2013

tough question: leave nils and expect injection in find methods or remove them and get JSON broken. I don't know..

@mikebaldry
Copy link

+1

@nicolasblanco
Copy link

+1.
My app is broken because of this patch. And this application does not even use ActiveRecord.

@homakov
Copy link
Contributor

homakov commented Jan 9, 2013

ok, +1 too

@simonx1
Copy link

simonx1 commented Jan 9, 2013

+1

@jeremy
Copy link
Member

jeremy commented Jan 9, 2013

We have +7 but no code proposed. Please do investigate!

@ceterumnet
Copy link

+1

@jlsync
Copy link

jlsync commented Jan 9, 2013

+1 on this issue. Perhaps the solution is to delete the key from the params hash rather than setting the value to nil (which is my current work-around in a before_filter ).

@TheBerg
Copy link

TheBerg commented Jan 9, 2013

+1

1 similar comment
@rainulf
Copy link

rainulf commented Jan 9, 2013

+1

@TheBerg
Copy link

TheBerg commented Jan 9, 2013

After investigating it some more, I totally understand why this was implemented the way it was implemented. Rails needs to be secure by default.

Maybe we should add a params_from_post_data method that would still let people get around this. Thoughts?

I am investigating if this would work in my own applications. If it works and people feel like it is a good work around I'll submit a patch.

@TheBerg
Copy link

TheBerg commented Jan 9, 2013

Params from post data would look kinda like this:

  def json_params
    @json_params ||= ActionController::Parameters.new(ActiveSupport::JSON.decode(request.body))
  end

But would need to handle XML, JSON, etc. Thoughts?

@mattgreen
Copy link

@TheJeff : I'm not sure why empty JSON arrays are a security problem in ActionPack.

They may be a problem for AR, but but that's AR's problem, not ActionPack's.

@TheBerg
Copy link

TheBerg commented Jan 9, 2013

Oh, ActionController::Parameters.new is part of StrongParameters & Rails4, not in Rails 3.

@TheBerg
Copy link

TheBerg commented Jan 9, 2013

@mattgreen I agree, but don't see a way to fix this issue without severely crippling ActiveRecord (basically disallowing searching for nil values).

Personally, I feel like this is a per-application security vulnerability, but at the same time I respect the Rails Cores team working to make Rails secure by default.

Another way to fix this would be to extend StrongParameters so that a require or allow would make sure that that value is not an Array or Hash, but that would require people to move to StrongParameters.

@mattgreen
Copy link

Requiring people to use StrongParameters in Rails 4 would be an acceptable resolution to this bug.

But mutilating data that comes in to cover the persistence layer's weaknesses is ridiculous. I'm assuming this bug was an oversight.

@wpeterson
Copy link

+1 This will likely break things for us as well.

@TheBerg
Copy link

TheBerg commented Jan 9, 2013

@mattgreen I believe it was an oversight, but also I don't really know of any other way to solve this issue without doing it. I am racking my brain for a solution and I just can't think of another one.

@Unpakt
Copy link

Unpakt commented Jan 9, 2013

We've created a before filter that will fix this issue until there is a new actionpack release see the gist here:

https://gist.github.com/4495772

@abuggia
Copy link

abuggia commented Jan 9, 2013

+1

2 similar comments
@edawerd
Copy link

edawerd commented Jan 9, 2013

+1

@xdaveyx
Copy link

xdaveyx commented Jan 9, 2013

+1

@imanel
Copy link
Contributor

imanel commented Nov 11, 2013

I would opt for removal of this - it's no longer necessary after permitted params were introduced.

@joshwlewis
Copy link

Looks like #11044 should solve this.

@jasonmp85
Copy link

LOL @ milestone 4.0.2.

"Hey guys, remember that time we broke compliance with JSON in a patch release? Well we're going to fix it in a patch release, too. Hope you didn't write any hacks to get around the asinine behavior."

@rafaelfranca
Copy link
Member

Like I said, the milestone doesn't mean it will be fixed on that milestone,
it is just to make sure we will revisit this issue when release that
milestone.
On Nov 13, 2013 8:52 PM, "Jason Petersen" notifications@github.com wrote:

LOL @ milestone 4.0.2.

"Hey guys, remember that time we broke compliance with JSON in a patch
release? Well we're going to fix it in a patch release, too. Hope you
didn't write any hacks to get around the asinine behavior."


Reply to this email directly or view it on GitHubhttps://github.com//issues/8832#issuecomment-28442476
.

@jasonmp85
Copy link

Ah. Serves me right to open my mouth before reading all the comments (though in all honestly I'm squelching this thread now because it's just been 👍s for months now).

@OmarSkalli
Copy link
Author

Can a contributor add the "Regression" label to this issue please?

@rafaelfranca
Copy link
Member

Agree with you we have to take a decision here. This is why I added the
milestone. I'll make sure we come with some solution before the 4.0.2
release. But it can be included only on 4.1.
On Nov 13, 2013 10:47 PM, "Jason Petersen" notifications@github.com wrote:

Ah. Serves me right to open my mouth before reading all the comments
(though in all honestly I'm squelching this thread now because it's just
been [image: 👍]s for months now).


Reply to this email directly or view it on GitHubhttps://github.com//issues/8832#issuecomment-28450070
.

@imanel
Copy link
Contributor

imanel commented Nov 14, 2013

@rafaelfranca what is the reason for deep munge after implementation of permitted params. From what I remember the reason was passing array instead of string, which is now prevented by default...

carpeliam added a commit to pophealth/popHealth that referenced this issue Dec 5, 2013
This works around a rails bug; see rails/rails#8832 for more details
carpeliam added a commit to pophealth/popHealth that referenced this issue Dec 5, 2013
This works around a rails bug; see rails/rails#8832 for more details
carpeliam added a commit to pophealth/popHealth that referenced this issue Dec 6, 2013
This works around a rails bug; see rails/rails#8832 for more details
@melcher
Copy link

melcher commented Dec 11, 2013

+1

4 similar comments
@mikeric
Copy link

mikeric commented Dec 12, 2013

+1

@luisobo
Copy link

luisobo commented Dec 13, 2013

👍

@vincentwoo
Copy link

+1

@11449
Copy link

11449 commented Dec 17, 2013

+1

@chancancode
Copy link
Member

Hey guys, thank you for submitting this and expressing your concerns about this issue! Speaking for myself, I understand where you are coming from, and I agree we could do better. Unfortunately, this PR does not meet our requirements for an acceptable solution to the problem.

Please stop responding with +1s and "me too"s. Those comments are only going to create noise for everyone and slow down the progress. We heard you loud and clear, and yes, we definitely care a lot about your opinion on this.

Instead, please head over to #13420 for the background and contribute your ideas. Thanks again! ❤️ 💚 💙 💛 💜

@rails rails locked and limited conversation to collaborators Aug 15, 2014
juliusv added a commit to prometheus-junkyard/promdash that referenced this issue Nov 7, 2014
This enables PUT-ing and GET-ing of full dashboard definitions through
/<slug>.json. In this API, the 'dashboards_json' database field is
converted from a JSON string to a native JSON suboject of the Rails
Dashboard model JSON. The full externally exposed JSON looks like this:

{
  "name": "Test Dashboard",
  "created_at": "2014-11-07T00:25:57.000Z",
  "updated_at": "2014-11-07T00:38:23.000Z",
  "dashboard_json": {
    "globalConfig": {
      // ...global configuration...
    },
    "widgets": [
      // ...widget definitions...
    ]
  }
}

Upon PUT, the 'dashboards_json' field is validated against the
JSON-schema definition in the file 'dashboard_schema.json' and then
saved again as a string in a single database field.

Since Rails converts JSON empty arrays to "nil" values by default, this
also upgrades PromDash to Rails 4.1.1, which supports an option to turn
off this automatic conversion. See the following issues about this
regarding security implications (which for now we shouldn't need to
worry about in PromDash):

rails/rails#8832
rails/rails#13420

Further, as we're exposing the dashboard_json as an external API for the
first time, this also includes a lot of naming cleanups in the JSON
fields and the related code.
juliusv added a commit to prometheus-junkyard/promdash that referenced this issue Nov 7, 2014
This enables JSON-schema-validated PUT-ing and GET-ing of full dashboard
definitions through /<slug>.json. In the external part of this API, the
'dashboards_json' database field is converted from a JSON-encoded string
to a native JSON subobject of the Rails Dashboard model JSON
representation. The full externally exposed JSON for a dashboard looks
like this:

{
  "name": "Test Dashboard",
  "created_at": "2014-11-07T00:25:57.000Z",
  "updated_at": "2014-11-07T00:38:23.000Z",
  "dashboard_json": {
    "globalConfig": {
      // ...global configuration...
    },
    "widgets": [
      // ...widget definitions...
    ]
  }
}

Upon PUT, the 'dashboards_json' field is validated against the
JSON-schema definition in the file 'dashboard_schema.json' and then
saved again as a serialized string in a single database field.

Since Rails converts empty JSON arrays to "nil" values by default, this
also upgrades PromDash to Rails 4.1.1, which supports an option to turn
off this automatic conversion. See the following issues about this
regarding security implications (which for now we shouldn't need to
worry about in PromDash):

rails/rails#8832
rails/rails#13420

Further, as we're exposing the dashboard_json as an external API for the
first time, this also includes a lot of naming cleanups in the JSON
fields and the related code.
juliusv added a commit to prometheus-junkyard/promdash that referenced this issue Nov 7, 2014
This enables JSON-schema-validated PUT-ing and GET-ing of full dashboard
definitions through /<slug>.json. In the external part of this API, the
'dashboards_json' database field is converted from a JSON-encoded string
to a native JSON subobject of the Rails Dashboard model JSON
representation. The full externally exposed JSON for a dashboard looks
like this:

{
  "name": "Test Dashboard",
  "created_at": "2014-11-07T00:25:57.000Z",
  "updated_at": "2014-11-07T00:38:23.000Z",
  "dashboard_json": {
    "globalConfig": {
      // ...global configuration...
    },
    "widgets": [
      // ...widget definitions...
    ]
  }
}

Upon PUT, the 'dashboards_json' field is validated against the
JSON-schema definition in the file 'dashboard_schema.json' and then
saved again as a serialized string in a single database field.

Since Rails converts empty JSON arrays to "nil" values by default, this
also upgrades PromDash to Rails 4.1.1, which supports an option to turn
off this automatic conversion. See the following issues about this
regarding security implications (which for now we shouldn't need to
worry about in PromDash):

rails/rails#8832
rails/rails#13420

Further, as we're exposing the dashboard_json as an external API for the
first time, this also includes a lot of naming cleanups in the JSON
fields and the related code.
vuntz added a commit to vuntz/barclamp-crowbar that referenced this issue Jan 8, 2015
This is breaking the JSON parsing for empty arrays, which we use with
the magic crowbar-deep-merge-template feature when creating the initial
crowbar proposal.

With deep munge enabled, we cannot remove the nagios proposal, which
results in failures when nagios barclamp is not available.

See:
rails/rails#8832
rails/rails#13420

We can revert this once switching to rails 5 (see comments in second
issue).
vuntz added a commit to vuntz/barclamp-crowbar that referenced this issue Jan 8, 2015
This is breaking the JSON parsing for empty arrays, which we use with
the magic crowbar-deep-merge-template feature when creating the initial
crowbar proposal.

With deep munge enabled, we cannot remove the nagios proposal, which
results in failures when nagios barclamp is not available.

See:
rails/rails#8832
rails/rails#13420

We can revert this once switching to rails 5 (see comments in second
issue).
vuntz added a commit to vuntz/barclamp-crowbar that referenced this issue Jan 9, 2015
This is breaking the JSON parsing for empty arrays, which we use with
the magic crowbar-deep-merge-template feature when creating the initial
crowbar proposal.

With deep munge enabled, we cannot remove the nagios proposal, which
results in failures when nagios barclamp is not available.

See:
rails/rails#8832
rails/rails#13420

We can revert this once switching to rails 5 (see comments in second
issue).
vuntz added a commit to vuntz/barclamp-crowbar that referenced this issue Jan 9, 2015
This is breaking the JSON parsing for empty arrays, which we use with
the magic crowbar-deep-merge-template feature when creating the initial
crowbar proposal.

With deep munge enabled, we cannot remove the nagios proposal, which
results in failures when nagios barclamp is not available.

See:
rails/rails#8832
rails/rails#13420

We can revert this once switching to rails 5 (see comments in second
issue).
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests